setbrush c++ qt paintevent

c++ - setbrush - ¿Cuándo un widget Qt obtiene un paintEvent?



qt5 qpainter (1)

Me pregunto en qué casos un widget recibe su evento de pintura, y cómo varía con el sistema operativo.

La documentación de Qt para paintEvent solo dice

Un evento de pintura es una solicitud para volver a pintar todo o parte de un widget. Puede suceder por una de las siguientes razones:

repaint () o update () fue invocado

el widget estaba oscurecido y ahora ha sido descubierto, o

muchas otras razones

Hasta ahora, he puesto algunas huellas en el evento paintEvent,

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

y esto es lo que descubrí (al menos en Windows 7):

Se llama a paintEvent cuando el widget pierde / gana foco. El evento de pintura no se llama cuando otro widget pasa sobre nuestro widget. No sé si eso se debe a la composición de Windows 7. El evento paintEvent también se invoca cuando se restaura una ventana minimizada. Se llama a paintEvent al redimensionar.

Entonces, ¿el comportamiento depende del sistema operativo?


Sí, en el sentido que usted describe, depende del sistema operativo.

Desktop Window Manager (DWM), que se encuentra en Windows Vista y 7, doohickey que es responsable de la composición del escritorio, el efecto Aero Glass y todo tipo de otros productos, funciona de manera diferente al modelo utilizado en versiones anteriores de Windows . Como sospecha, almacena en caché los mapas de bits de sus ventanas, incluso cuando no son visibles porque están oscurecidas por otra ventana. Eso significa que no necesita que se vuelvan a pintar (y, por lo tanto, no provoca un evento de pintura), ya que solo puede modificarlos desde el mapa de bits en caché. No solo se trata de una optimización potencial para que cada aplicación se rediseñe a sí misma, sino que también permite que DWM implemente cosas como Aero Flip, para lo cual utiliza su mapa de bits en caché.

La excepción a esto es como siempre ha sido para, digamos, el estilo de clase CS_SAVEBITS . Si el mapa de bits que el DWM ha almacenado en caché se ha invalidado (por ejemplo, porque la imagen de su ventana ha cambiado), lo descartará y le pedirá que vuelva a dibujar la ventana.

Pruebe esta teoría desactivando la composición DWM (cambiando al tema "Windows Classic") y luego oscureciendo su ventana para ver si recibe un evento de pintura. Debería, al igual que lo hizo en todas las versiones anteriores de Windows.

Pero el punto más importante es que no debe confiar en recibir eventos de pintura en un orden particular. Lo único que debe suponer sobre los eventos de pintura es que recibirá uno cuando el sistema operativo necesite volver a pintar la ventana. De lo contrario, no te molestará. Estoy seguro de que es por eso que la documentación se contenta con ser vago en este punto, más allá de las posibles limitaciones técnicas.

Esta es la razón por la cual la lógica no debe ir dentro del controlador de eventos de pintura. De lo único que debe encargarse el método es repintar la ventana según su estado actual . Ese estado necesita ser guardado en otro lugar. Esta regla también es conmutativa: no debe hacer ninguna pintura fuera del controlador de eventos de pintura.

Por supuesto, siempre se puede forzar la aparición de un evento de pintura invalidando su ventana (estoy seguro de que Qt tiene un método de invalidate o refresh para esto, consulte la documentación), pero eso aún no significa que sea un buen patrón para colocar. lógica de aplicación en el método que maneja este evento.