当 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 冻结的主要内容,如果未能解决你的问题,请参考以下文章
当 CPU 负载为 100%(主要使用 C++ 和 Qt)时,如何保持 UI 响应?
当 MainWindow 从另一个类(不在主函数中)启动时,QT ui 未显示