MyWindow,它继承自QMainWindow。MyWindow包含一个显示动画的QGLWidget。
问题是,每当我打开菜单或调整窗口大小时,动画都会暂停。
动画是通过周期性地调用QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest))
来实现的,然后每次窗口接收到QEvent::UpdateRequest
时都调用重绘,如下所示:
bool MyWindow::event(QEvent *event)
{
qDebug() << event;
switch (event->type())
{
case QEvent::UpdateRequest:
render();
return true;
default:
return QMainWindow::event(event);
}
}
从qDebug()
可以看出,当菜单打开或窗口正在调整大小时,窗口将停止接收更新请求事件。
QMainWindow/QWidget上是否有设置使其继续接收更新请求事件?或者有更好的方法来实现动画吗?
编辑:我在Mac OS X上。
这可能是一个Qt错误。我会调查的。
唉,你的代码太复杂了。
-
postEvent
应该简单地由this->update()
代替。它在幕后为您发布活动。 -
可以简单地将QTimer实例的信号连接到
widget, SLOT(update())
。如果要保存在QObject
实例上,请使用QBasicTimer
并重新实现timerEvent
,如下所示:void MyWidget::timerEvent(QTimerEvent* ev) { if (ev.timerId() == m_timer.timerId()) update(); }
-
不需要处理
event()
的重新实现。只需重新实现paintEvent()
——这就是它的用途。
Qt GUI更新正在MainThread上执行。所以,若同时拥有许多gui功能,那么缓慢的gui响应是合理的。所以一般来说,不要用太多繁重的函数调用来重载MaiThread。
加速GUI响应的可能解决方案。
- 如果PostEvent是由您的MainThread调用的(如果您使用的是来自主gui线程的计时器),请将其移动到中的后端功能工作线程和postEvent
- 在render()之后调用QCoreApplication::processEvents();函数。这将有助于系统在继续之前处理事件循环中的所有其他事件
请查看以下链接如何改进GUI响应
注意:当创建和触发计时器时,默认情况下它将在您的线程中运行,它不会启动另一个线程。
由于我没有从Kuba Ober那里听到任何关于这可能是Qt错误的消息,我继续提交了一份错误报告:https://bugreports.qt-project.org/browse/QTBUG-33382
通过更直接地调用render()
函数,我能够部分地解决这个问题——也就是说,不用发送事件、接收事件并让事件处理程序调用该函数。我用一个调度队列(但不是主调度队列,因为它与默认的运行循环绑定,所以它也有同样的问题)完成了这项工作。然而,在多个线程上使用QGLWidget是很困难的。在尝试使用moveToThread()
函数来实现这一功能一段时间后,并考虑到项目中涉及的其他因素,我决定使用Qt之外的其他东西来显示此窗口。