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

Posted

技术标签:

【中文标题】当 GL 更新大于 15 Hz 时 Qt UI 冻结【英文标题】:Qt UI freezes when GL update greater 15 Hz 【发布时间】:2014-10-29 07:32:09 【问题描述】:

我有一个带有工作线程的 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();

【问题讨论】:

【参考方案1】:

查看文档QTimer。 尤其是这部分:

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

还有这个:

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

【讨论】:

但是我正在工作线程中创建和启动计时器,在void cWorker::init()。我不明白该怎么做。你是说我根本不应该使用计时器吗?你能给出一个代码示例吗?我应该在哪里打电话给QThread::exec()?谢谢!

以上是关于当 GL 更新大于 15 Hz 时 Qt UI 冻结的主要内容,如果未能解决你的问题,请参考以下文章

Qt Qt中实时更新UI程序示例

QT 不更新 UI

当 CPU 负载为 100%(主要使用 C++ 和 Qt)时,如何保持 UI 响应?

当 MainWindow 从另一个类(不在主函数中)启动时,QT ui 未显示

更新 QJsonArray 中的值并写回 Qt 中的 Json 文件

jQuery UI 可拖动 - 当内部元素大于父元素时,将内部元素约束在父元素中