Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: jlstreckerОтветов: 3

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.

  • Возможно связано: NSEventTrackingRunLoopMode. См., например, stackoverflow .com/questions/10881122/ jlstrecker 04.09.2013

qtqt5qwidgetqmainwindowqevent

Ответы

Ответ 1 · рейтинг 1 · Kuba hasn't forgotten Monica

Это может быть ошибка 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() - вот для чего он нужен.

Ответ 2 · Ashif

Обновления 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

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

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

Ответ 3 · jlstrecker

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы