QMainWindow перестает получать QEvent::UpdateRequest, когда пользователь открывает меню или изменяет размер окна

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.


person jlstrecker    schedule 03.09.2013    source источник
comment
Возможно связано: NSEventTrackingRunLoopMode. См., например, stackoverflow .com/questions/10881122/   -  person jlstrecker    schedule 04.09.2013


Ответы (3)


Это может быть ошибка Qt. Я расследую.

Увы, вы слишком усложняете свой код.

  1. postEvent следует просто заменить на this->update(). За кулисами он публикует событие для вас.

  2. Можно просто подключить сигнал экземпляра QTimer к widget, SLOT(update()). Если вы хотите сэкономить на экземпляре QObject, используйте QBasicTimer и переопределите timerEvent следующим образом: void MyWidget::timerEvent(QTimerEvent* ev) { if (ev.timerId() == m_timer.timerId()) update(); }

  3. Нет необходимости иметь дело с event() повторной реализацией. Просто переопределите paintEvent() - вот для чего он нужен.

person Kuba hasn't forgotten Monica    schedule 03.09.2013
comment
Спасибо за расследование. Что касается предлагаемых очисток, я попробовал (1) и (3) и обнаружил, что, хотя комбинация update() и paintEvent() не работает (я не получал никаких событий рисования и почти никаких событий запросов на обновление), я был возможность использовать комбинацию repaint() и event(). Итак, немного проще, но, конечно, это не решает исходную проблему. - person jlstrecker; 05.09.2013

Обновления Qt GUI выполняются в MainThread. Таким образом, медленный отклик графического интерфейса является разумным, если у вас одновременно выполняется много функций графического интерфейса. В общем, не перегружайте MaiThread таким количеством сложных вызовов функций.

Вероятное решение для ускорения ответа вашего графического интерфейса.

  1. Если PostEvent вызывается вашим MainThread (если вы используете таймер из основного потока графического интерфейса), вместо этого переместите их в бэкэнд-функции в рабочем потоке и postEvent после того, как это будет сделано.
    • you call QCoreApplication::processEvents(), after your render(); function in MainThread. This will help system to process all the other events that are in the event-loop before to continue

Пожалуйста, проверьте, следуя ссылке Как улучшить отклик графического интерфейса

Примечание. При создании и запуске таймера он будет работать в вашем потоке по умолчанию, он не будет запускать другой поток.

person Ashif    schedule 04.09.2013
comment
Это не медленный ответ графического интерфейса — это отсутствие ответа. Окно перестает получать события запроса на обновление, пока открыто меню или изменяется размер окна. - person jlstrecker; 04.09.2013
comment
Я думаю, postEvent вызывается неправильно, может быть, он может перестать отправлять сообщение в ваш графический интерфейс. - person Ashif; 04.09.2013

Поскольку я больше ничего не слышал от Кубы Обера о возможности того, что это ошибка Qt, я пошел дальше и отправил отчет об ошибке: https://bugreports.qt-project.org/browse/QTBUG-33382

Мне удалось частично обойти проблему, вызвав функцию render() более напрямую, т. е. вместо отправки события, получения события и вызова функции обработчиком события. Я выполнил это с помощью очереди отправки (но не основной очереди отправки, поскольку она привязана к циклу выполнения по умолчанию, поэтому у нее та же проблема). Однако работать с QGLWidget в нескольких потоках было сложно. Попробовав какое-то время использовать функцию moveToThread(), чтобы заставить это работать, и учитывая другие факторы, связанные с проектом, я решил использовать что-то другое, кроме Qt, для отображения этого окна.

person jlstrecker    schedule 07.09.2013