仅在关闭窗口时才更新带有计时器的 QT 画家更新

Posted

技术标签:

【中文标题】仅在关闭窗口时才更新带有计时器的 QT 画家更新【英文标题】:QT painter update with timer only update when close window 【发布时间】:2013-07-30 07:15:59 【问题描述】:

我有一些数据会不断变化。我通过 QPainter 将这些数据绘制成一行,并希望通过 QTimer 进行动态更新(每秒更新一次),但数据只会在我关闭绘画窗口时更新,它不会在窗口中实时更新。我哪里错了?? 代码如下:

#include <QtGui/QApplication>
#include <QApplication>
#include <QLabel>
#include <QWidget>
#include <QPainter>
#include <QTimer>

#define WINDOW_H 512
#define WINDOW_W 512

unsigned char *pMergedData; 

class DrawDemo : public QWidget 
    Q_OBJECT
public: 
    DrawDemo( QWidget *parent=0); 
public slots:
    void MyUpdate();
protected:
    void paintEvent(QPaintEvent*);
private:
    QTimer *timer; 
; 

void DrawDemo::MyUpdate()
    test_plot();
    update();


DrawDemo::DrawDemo( QWidget *parent) :QWidget(parent) 
    pMergedData = (unsigned char *)malloc(200*sizeof(short));
    QTimer *timer = new QTimer(this); 
    connect( timer, SIGNAL( timeout() ), this, SLOT(  MyUpdate()  ) ); 
    timer->start( 1000 ); //ms 
 

void DrawDemo::paintEvent( QPaintEvent * ) 
    short *buf16 = (short *)pMergedData;

    QPainter painter( this );
    QPoint beginPoint;
    QPoint endPoint; 

    painter.setPen(QPen(Qt::red, 1));
    for( int i=0; i<199; i++ ) 
        beginPoint.setX( 2*i );
        beginPoint.setY( WINDOW_H - buf16[i] ); 
        endPoint.setX( 2*i+1 );
        endPoint.setY( WINDOW_H - buf16[i+1]);
        painter.drawLine( beginPoint, endPoint );
    
 

int test_plot()

    counter_globol ++;
    if(counter_globol%2==0)
        for(int i=0; i<200; i++ )  
            pMergedData[i] = 100;
          
    else
            for(int i=0; i<200; i++ )  
            pMergedData[i] = i;
         
    

    return 0;


int main(int argc, char *argv[])

    QApplication a(argc, argv);

    DrawDemo *drawdemo = new DrawDemo( 0 ); 
    drawdemo->setWindowTitle("QPainter");
    drawdemo->resize(WINDOW_W, WINDOW_H);
    drawdemo->show();

    a.exec();
    free(pMergedData);
    return 0;

【问题讨论】:

您在此期间无限次调用a.exec()。可能不是问题。但有些东西肯定需要修复。 【参考方案1】:

仅当您关闭窗口时才会更新,因为您的代码结构错误。

a.exec() 函数启动程序的主事件循环,该循环处理所有正在发生的事件,例如鼠标移动、按钮按下和计时器。在窗口关闭之前它不会退出函数。此时,a.exec() 预计程序正在完成。

在您发布的代码中,它为行设置数据,创建小部件,然后使用 a.exec() 启动消息处理程序。现在,这些行永远不会改变,因为 pMergedData 中的数据永远不会被再次调用,直到窗口关闭,但 a.exec() 不应该以这种方式处理。

当您关闭窗口并重新打开它时,a.exec() 函数会返回,并且由于您的 while 循环,pMergedData 中的数据会重新初始化并创建一个新窗口。

所以,要解决这个问题,你需要这样的东西:-

int main(int argc, char *argv[])

    QApplication a;

    DrawDemo *drawdemo = new DrawDemo( 0 ); 
    drawdemo->setWindowTitle("QPainter");
    drawdemo->resize(WINDOW_W, WINDOW_H);
    drawdemo->show();   

    a.exec();
    return 0;

如您所见,我已将 QApplication 和 DrawDemo 对象的创建移出 test_plot 函数。由于您希望数据每秒更改一次,因此您还应该每秒调用 test_plot,因此不要让计时器每秒调用小部件函数更新,而是创建自己的函数 MyUpdate 并连接到该函数:-

void DrawDemo::MyUpdate()

    test_plot();
    update();

【讨论】:

感谢您的回复。但是当我创建另一个函数来包装 update() 时,它不会在超时时进行更新。将我的计时器连接更改为:'connect(timer, SIGNAL(timeout()), this, SLOT(MyUpdate()))' 是否正确? 是的,但如果它不起作用,请在您的问题中添加编辑并向我们展示代码。导致问题的原因可能很简单。 每次输入函数 test_plot 时,您都会使用 malloc 为 pMergedData 创建一个新的点数组。这应该只做一次,要么在 main 中(因为它是一个全局变量),要么更好地将数组移动到类中并在构造函数中初始化它。 我还注意到您缺少 Q_OBJECT 宏,该宏需要在声明类之后放置在您的标题中。所以就在这行之后, class DrawDemo : public QWidget Q_OBJECT.您需要它来使信号和插槽正常工作。 终于可以实时更新了!非常感谢您帮我找到问题!!

以上是关于仅在关闭窗口时才更新带有计时器的 QT 画家更新的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose:批量更新插入,但仅在满足某些条件时才更新记录

仅在重新渲染组件时才反应状态更新

不断更新OpenGL窗口

怎样使对话框关不了

Qt 中的 GLWidget 仅在 mousemove 上更新

JavaScript进阶