• 9376阅读
  • 5回复

[讨论]画波形图闪烁 [复制链接]

上一主题 下一主题
离线lzpmail
 
只看楼主 倒序阅读 楼主  发表于: 2011-04-09
下面是我写的一个程序的小部分,主线程主要是画波形图,但其波形图的数据放在一个子线程中处理,我现在是想一有波形数据我就把它画出来,更新波形(我现在是用invokeMethod来调用selfRepaint()函数来刷新屏幕),不知是什么原因,画pixmap的地方老是一闪一闪的(我的波形画在QPixmap上),并且打印出QPixmap: It is not safe to use pixmaps outside the GUI thread,且波形不显示出来。请高手指点下pixmap为什么会闪,有没有更好的办法只要子线程收到波形数据就立即通知主线程画出来(要实时),谢谢
[code][/code]
//主线程
void UrineCheck::paintEvent(QPaintEvent *event)
{
//    QPainter painter;
    if (true == ecg1NeedDraw)
    {
        ecg1NeedDraw = false;
        drawEcg1Wave();
        drawEcg2Wave();
    }

    if (true == spo2NeedDraw)
    {
        spo2NeedDraw = false;
        drawSpo2Wave();
    }
//    if (true == respNeedDraw)
//    {
//        respNeedDraw = false;
//        drawRespWave();
//    }
}
int WaveEcg1X=0, WaveEcg1Y=60;
void UrineCheck::drawEcg1Wave(/*QPainter &ecg1Painter*/)
{
    if (ecg1DrawData.isEmpty())
        return;
    int yPos;
    QQueue<int> tempQue = ecg1DrawData;
    ecg1DrawData.clear();

    QPainterPath painterPath;
    QPen linePen(Qt::green);
    QPainter ecg1Painter;

    ecg1Painter.begin(pixEcg1);
    ecg1Painter.setPen(linePen);

    //=================================================鏄捐蹇冭烦
    if (GetResampleRPeak(gEcg1SpeedScale))
    {

    }

    //==================================================鐢绘尝褰?    painterPath.moveTo(WaveEcg1X, WaveEcg1Y);
    while (!tempQue.isEmpty())
    {
        yPos = tempQue.dequeue();
        if (WaveEcg1X > ECG1WIDTH)
        {
            WaveEcg1X = 0;
            painterPath.moveTo(WaveEcg1X, WaveEcg1Y);
        }
        WaveEcg1Y = ECG1HEIGHT - ECG1HEIGHT/2 - (yPos-0x800)*5*ECG1HEIGHT/0x1000/2;
//        printf("wave Ecg1 Ypos: %d\n", WaveEcg1Y);
        if (WaveEcg1Y < 0)
            WaveEcg1Y = 0;
        if (WaveEcg1Y > ECG1HEIGHT)
            WaveEcg1Y = ECG1HEIGHT;

        ecg1Painter.fillRect(WaveEcg1X, 0, 5, ECG1HEIGHT, Qt::black);
        painterPath.lineTo(WaveEcg1X++, WaveEcg1Y);
    }
    ecg1Painter.drawPath(painterPath);
    painterPath.closeSubpath();
    //==================================================   鏄捐pace
    QPen pacePen(Qt::red);
    ecg1Painter.setPen(pacePen);
    if (GetResamplePace(gEcg1SpeedScale) && ON == gEcgConfig.paced)
    {
        painterPath.moveTo(WaveEcg1X, 2);
        painterPath.lineTo(WaveEcg1X, ECG1HEIGHT-2);
        ecg1Painter.drawPath(painterPath);
    }
    ecg1Painter.end();
    ecg1Painter.begin(this);
    ecg1Painter.setRenderHint(QPainter::Antialiasing);
    ecg1Painter.translate(400, 240);           //鍙樻崲鍘熺偣鍧愭爣
    ecg1Painter.drawPixmap(-400, -240, *pixEcg1);
    ecg1Painter.end();
}

void UrineCheck::seflRepaint()
{
    repaint();
}

//子线程
VOID UrineShowThread::DrawEcg1Wave(UINT wParam)
{
//     INT16 resample_data[RESAMPLE_MAX_NUM];
     // 閲嶉噰鏍峰鐞? wParam鍊肩殑鑼冨洿鍦?锛?096锛屾鍑芥暟浣滅敤鎶妛Param鍊兼斁鍒皊ample鏁扮粍涓?澶у皬涓?0
     UpdateResampleWaveData( gEcg1SpeedScale, wParam);
     UpdateResampleRPeak( gEcg1SpeedScale, gFlagMan.IsRPeak());
     UpdateResamplePace( gEcg1SpeedScale, gFlagMan.IsPacePulse());

     // move the ecg wave buffer read pointer
     gEcg1WaveBufReadPtr++;
     if ( gEcg1WaveBufTail < gEcg1WaveBufReadPtr )
         gEcg1WaveBufReadPtr = gEcg1WaveBufHead;

     if (CanResampleWaveData(gEcg1SpeedScale))
     {
//         Resample(gEcg1SpeedScale, resample_data);
         Resample(gEcg1SpeedScale, ecg1DrawData);
     }
     else
         return;

     ecg1NeedDraw = true;
     QMetaObject::invokeMethod(parent, "seflRepaint", Qt::DirectConnection);
}
离线wxj120bw

只看该作者 1楼 发表于: 2011-04-09
引用楼主lzpmail于2011-04-09 17:04发表的 画波形图闪烁 :
下面是我写的一个程序的小部分,主线程主要是画波形图,但其波形图的数据放在一个子线程中处理,我现在是想一有波形数据我就把它画出来,更新波形(我现在是用invokeMethod来调用selfRepaint()函数来刷新屏幕),不知是什么原因,画pixmap的地方老是一闪一闪的(我的波形画在QPixmap上),并且打印出QPixmap: It is not safe to use pixmaps outside the GUI thread,且波形不显示出来。请高手指点下pixmap为什么会闪,有没有更好的办法只要子线程收到波形数据就立即通知主线程画出来(要实时),谢谢

//主线程
void UrineCheck::paintEvent(QPaintEvent *event)
{
.......

程序还没看 不过可以考虑用connect函数将信号连接信号连续发送到主线程
离线lzpmail
只看该作者 2楼 发表于: 2011-04-10
信号槽响应太慢,我现在是用invokeMethod()函数来调用selfRepaint(), selfRepaint()里只有一个repaint()语句,这个响应还比较快,但seflRepaint()在子线程里运行,而画图呢又只能在主线程中画,真叫我头痛啊,现在不知如何是好
离线wxj120bw

只看该作者 3楼 发表于: 2011-04-10
引用第2楼lzpmail于2011-04-10 10:43发表的  :
信号槽响应太慢,我现在是用invokeMethod()函数来调用selfRepaint(), selfRepaint()里只有一个repaint()语句,这个响应还比较快,但seflRepaint()在子线程里运行,而画图呢又只能在主线程中画,真叫我头痛啊,现在不知如何是好

你考虑过connect函数第五个参数的作用吗
离线lzpmail
只看该作者 4楼 发表于: 2011-04-11
考虑了,以前我看过一篇文章,说信号槽的响应时间要100多毫秒,不知是否真有这么慢,如果真有这么慢,在这个程序里肯定是不能用的
离线lzpmail
只看该作者 5楼 发表于: 2011-04-11
我刚在子线程中用信号槽:如下,那个drawEcg1Wave()函数是继承QWidget类中的函数,也贴在下面。当我在2440的板子上跑我那个程序时,打印出QPixmap: It is not safe to use pixmaps outside the GUI thread, 这知道这话意思是说在非GUI线程中画图不安全。我现在的问题是当我发送信号后,怎么让drawEcg1Wave()函数在主线程中运行呢。 谢谢
UrineShowThread::UrineShowThread(QDialog *par)
    :parent(par)
{
    connect(this, SIGNAL(callMainProcessRepaint()), parent, SLOT(drawEcg1Wave()), Qt::DirectConnection);
}

VOID UrineShowThread::DrawEcg1Wave(UINT wParam)
{
//     INT16 resample_data[RESAMPLE_MAX_NUM];
     // 閲嶉噰鏍峰鐞? wParam鍊肩殑鑼冨洿鍦?锛?096锛屾鍑芥暟浣滅敤鎶妛Param鍊兼斁鍒皊ample鏁扮粍涓?澶у皬涓?0
     UpdateResampleWaveData( gEcg1SpeedScale, wParam);
     UpdateResampleRPeak( gEcg1SpeedScale, gFlagMan.IsRPeak());
     UpdateResamplePace( gEcg1SpeedScale, gFlagMan.IsPacePulse());

     // move the ecg wave buffer read pointer
     gEcg1WaveBufReadPtr++;
     if ( gEcg1WaveBufTail < gEcg1WaveBufReadPtr )
         gEcg1WaveBufReadPtr = gEcg1WaveBufHead;

     if (CanResampleWaveData(gEcg1SpeedScale))
     {
//         Resample(gEcg1SpeedScale, resample_data);
         Resample(gEcg1SpeedScale, ecg1DrawData);
     }
     else
         return;
     ecg1NeedDraw = true;

     emit callMainProcessRepaint();       //在此处发送信号
}

void UrineCheck::drawEcg1Wave(/*QPainter &ecg1Painter*/)
{
    if (ecg1DrawData.isEmpty())
        return;
    int yPos;
    QQueue<int> tempQue = ecg1DrawData;
    ecg1DrawData.clear();

    QPainterPath painterPath;
    QPen linePen(Qt::green);
    QPainter ecg1Painter;

    ecg1Painter.begin(pixEcg1);
    ecg1Painter.setPen(linePen);

    //=================================================鏄捐蹇冭烦
    if (GetResampleRPeak(gEcg1SpeedScale))
    {

    }

    //==================================================鐢绘尝褰?    painterPath.moveTo(WaveEcg1X, WaveEcg1Y);
    while (!tempQue.isEmpty())
    {
        yPos = tempQue.dequeue();
        if (WaveEcg1X > ECG1WIDTH)
        {
            WaveEcg1X = 0;
            painterPath.moveTo(WaveEcg1X, WaveEcg1Y);
        }
        WaveEcg1Y = ECG1HEIGHT - ECG1HEIGHT/2 - (yPos-0x800)*5*ECG1HEIGHT/0x1000/2;
//        printf("wave Ecg1 Ypos: %d\n", WaveEcg1Y);
        if (WaveEcg1Y < 0)
            WaveEcg1Y = 0;
        if (WaveEcg1Y > ECG1HEIGHT)
            WaveEcg1Y = ECG1HEIGHT;

        ecg1Painter.fillRect(WaveEcg1X, 0, 5, ECG1HEIGHT, Qt::black);
        painterPath.lineTo(WaveEcg1X++, WaveEcg1Y);
    }
    ecg1Painter.drawPath(painterPath);
    painterPath.closeSubpath();
    //==================================================   鏄捐pace
    QPen pacePen(Qt::red);
    ecg1Painter.setPen(pacePen);
    if (GetResamplePace(gEcg1SpeedScale) && ON == gEcgConfig.paced)
    {
        painterPath.moveTo(WaveEcg1X, 2);
        painterPath.lineTo(WaveEcg1X, ECG1HEIGHT-2);
        ecg1Painter.drawPath(painterPath);
    }
    ecg1Painter.end();
    repaint(0, 0, ECG1WIDTH, ECG1HEIGHT);
}
快速回复
限100 字节
 
上一个 下一个