Подтвердить что ты не робот

Когда виджет Qt получает paintEvent?

Мне интересно, в каких случаях виджет получает свое событие рисования и как он отличается от ОС.

Документация Qt для paintEvent говорит только

Событие рисования - это запрос на перерисовку всего или части виджета. Это может произойти по одной из следующих причин:

Вызывается

repaint() или update(),

виджет был затенен и теперь открыт, или

много других причин.

До сих пор я помещал некоторые следы в paintEvent,

void Widget::paintEvent(QPaintEvent *e)
{
    static int count = 0;
    qDebug("paintEvent, %d", count++);
}

и это то, что я узнал (по крайней мере на Windows 7):

PaintEvent вызывается, когда виджет теряет/получает фокус. Событие paint не вызывается, когда другой виджет проходит через наш виджет. Я не знаю, что из-за компоновки Windows 7. PaintEvent также вызывается, когда восстанавливается свернутое окно. При изменении размера вызывается paintEvent.

Итак, поведение зависит от ОС?

4b9b3361

Ответ 1

Да, в том смысле, что вы описываете, он зависит от операционной системы.

Диспетчер окон рабочего стола (DWM), найденный в Windows Vista и 7, doohickey, который отвечает за компоновку рабочего стола, эффект Aero glass и всевозможные другие глазные конфеты, работает немного иначе, чем модель, используемая в предыдущих версии Windows. Как вы подозреваете, он кэширует растровые изображения для ваших окон, даже когда они не видны, потому что они закрыты другим окном. Это означает, что вам не нужно перерисовывать их (и, следовательно, он не вызывает событие рисования), потому что он может просто выпустить их из кэшированного растрового изображения. Это не только потенциальная оптимизация, связанная с тем, что каждое приложение перерисовывает себя, но также позволяет DWM реализовывать такие вещи, как Aero Flip, для которых он использует свое кэшированное растровое изображение.

Исключением является то, что это всегда было, скажем, для стиля класса CS_SAVEBITS. Если битмап, который был зашифрован DWM, стал недействительным (например, из-за изменения изображения в окне), он отменит его и попросит перерисовать окно.

Протестируйте эту теорию, отключив композицию DWM (переключитесь на тему "Windows Classic" ), а затем затеняя свое окно, чтобы увидеть, получилось ли событие рисования. Вы должны, как и во всех предыдущих версиях Windows.

Но главное - вы не должны полагаться на получение событий рисования в любом конкретном порядке. Единственное, что вы должны принять в отношении событий рисования, это то, что вы получите его, когда операционной системе нужно перекрасить ваше окно. В противном случае это вас не беспокоит. Я уверен, что почему документация довольна тем, что она неопределенная по этому вопросу, помимо возможных технических ограничений.

Вот почему логика не должна проходить внутри обработчика событий рисования. Единственное, за что должен отвечать этот метод, - это перекрасить окно по его текущему состоянию. Это состояние необходимо сохранить в другом месте. Это правило также является коммутативным: вы не должны рисовать за пределами обработчика событий рисования.

Конечно, вы всегда можете заставить событие paint быть поднятым путем аннулирования вашего окна (я уверен, что Qt имеет метод invalidate или refresh для этого, проверьте документацию), но это все еще не означает хороший шаблон для размещения логики приложения в методе, который обрабатывает это событие.