【问题标题】:QMainWindow stops receiving QEvent::UpdateRequest when user opens menu or resizes window当用户打开菜单或调整窗口大小时,QMainWindow 停止接收 QEvent::UpdateRequest
【发布时间】:2013-09-03 19:55:55
【问题描述】:

MyWindow 继承自 QMainWindow。 MyWindow 包含一个显示动画的 QGLWidget。

问题是每当我打开菜单或调整窗口大小时动画都会暂停。

动画是通过周期性调用QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest))来实现的,然后每次窗口收到QEvent::UpdateRequest时调用redrawing,像这样:

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 qt5 qwidget qmainwindow qevent


【解决方案1】:

这可能是一个 Qt 错误。我会调查的。

唉,您的代码过于复杂了。

  1. postEvent 应简单地替换为 this-&gt;update()。它在幕后为您发布事件。

  2. 可以简单地将 QTimer 实例的信号连接到 widget, SLOT(update())。如果要保存在 QObject 实例上,请使用 QBasicTimer 并重新实现 timerEvent,如下所示:void MyWidget::timerEvent(QTimerEvent* ev) { if (ev.timerId() == m_timer.timerId()) update(); }

  3. 无需处理event() 的重新实现。只需重新实现 paintEvent() - 这就是它的用途。

【讨论】:

  • 感谢您的调查。至于建议的清理,我尝试了 (1) 和 (3),发现虽然 update()paintEvent() 的组合不起作用(我没有收到任何绘画事件,也几乎没有任何更新请求事件),我可以使用repaint()event() 的组合。所以,稍微简单一些,但它当然不能解决原来的问题。
【解决方案2】:

Qt GUI 更新正在 MainThread 上执行。如果您同时有许多 gui 功能,那么缓慢的 gui 响应是合理的。所以一般来说,不要用这么多繁重的函数调用来重载 MaiThread。

加快 GUI 响应速度的可能解决方案。

  1. 如果您的 MainThread 调用 PostEvent(如果您正在使用主 gui 线程中的计时器),则将它们移至后端功能 完成后的工作线程和 postEvent。
    • 在你的 render() 之后调用 QCoreApplication::processEvents(); MainThread 中的函数。 这将帮助系统在继续之前处理事件循环中的所有其他事件

请检查,以下链接How to improve GUI response

注意:当创建和触发计时器时,它会默认在你的线程中运行,它不会启动另一个线程。

【讨论】:

  • 这不是缓慢的 GUI 响应——它没有响应。只要打开菜单或调整窗口大小,窗口就会停止接收更新请求事件。
  • 我认为 postEvent 调用不正确,可能是它可能会停止向您的 GUI 发送消息。
【解决方案3】:

由于我没有从 Kuba Ober 那里听到任何关于这可能是 Qt 错误的消息,我继续提交了错误报告:https://bugreports.qt-project.org/browse/QTBUG-33382

我能够部分通过更直接地调用render() 函数来解决这个问题——也就是说,不是发送事件,而是接收事件,然后让事件处理程序调用函数.我用一个调度队列完成了这个(但不是主调度队列,因为它与默认的运行循环相关,所以它有同样的问题)。然而,在多线程上使用 QGLWidget 是很困难的。在尝试了一段时间使用moveToThread() 函数来完成这项工作后,并考虑到项目中涉及的其他因素,我决定使用Qt 以外的其他东西来显示这个窗口。

【讨论】:

    猜你喜欢
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 2019-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多