当GL更新大于15 Hz时,Qt UI冻结

Qt UI freezes when GL update greater 15 Hz

本文关键字:Qt UI 冻结 Hz GL 更新 大于      更新时间:2023-10-16

我有一个带有工作线程的Qt应用程序。工作线程使用2个QTimer以不同频率执行2个函数void cWorker::updDynamics()void cWorker::updGraphics()

updGraphics()连接到主线程中class GLWidget : public QGLWidget中的一个插槽,该插槽仅调用updateGL();

我的问题是,如果我的图形更新率>15 Hz,我的主窗口会冻结(GL小部件会更新,但我无法调整窗口大小或单击按钮)。为什么会发生这种情况,我该如何避免这个问题?-我想至少更新50Hz。

cWorker::cWorker()
{
    m_vertex = 0.1;    
}
void cWorker::init()
{
    int upd_rate_dynamics = 1000; //Hz
    int upd_rate_graphics = 15; //Hz
    m_timer_dynamics = new QTimer(this);
    connect(m_timer_dynamics, SIGNAL( timeout() ), this, SLOT( updDynamics() ));
    m_timer_dynamics->start(1000.0/upd_rate_dynamics);
    m_timer_graphics = new QTimer(this);
    connect(m_timer_graphics, SIGNAL( timeout() ), this, SLOT( updGraphics() ));
    m_timer_graphics->start(1000.0/upd_rate_graphics);
}
void cWorker::updDynamics()
{
    std::cout << "cWorker::updDynamics()" << std::endl;
    m_vertex += 0.0005;
}
void cWorker::updGraphics()
{
    std::cout << "cWorker::updGraphics()" << std::endl;
    emit requestRepaint();
}

int main(int argc, char *argv[])
{
    cWorker* worker = new cWorker();
    QThread* thread = new QThread;
    worker->moveToThread(thread);
    QObject::connect(thread, SIGNAL(started()), worker, SLOT(init()) );
    thread->start();
    QApplication a(argc, argv);
    MainWindow w;
    GLWidget *my_gl_widget = w.findChild<GLWidget*>("widget");
    my_gl_widget->m_worker_ptr = worker;
    QObject::connect(worker, SIGNAL( requestRepaint() ), my_gl_widget, SLOT( receiveRepaint() ));
    w.show();
    return a.exec();
}

查看文档QTimer。特别是这部分:

在多线程应用程序中,可以在任何具有事件循环的线程中使用QTimer。要从非GUI线程启动事件循环,请使用QThread::exec()。Qt使用计时器的线程相关性来确定哪个线程将发出timeout()信号。因此,您必须在其线程中启动和停止计时器;不可能从另一个线程启动计时器。

这个:

从那时起,processOneThing()将被反复调用。它应该以这样一种方式编写,即它总是快速返回(通常在处理一个数据项之后),以便Qt可以将事件传递到用户界面,并在完成所有工作后立即停止计时器。这是在GUI应用程序中实现繁重工作的传统方式,但随着多线程在越来越多的平台上变得可用,我们预计零毫秒的QTimer将逐渐被QThread所取代。