Qt小部件何时获得paintEvent?

sas*_*alm 19 c++ qt paintevent

我想知道小部件在哪些情况下接收它的绘制事件,以及它如何随操作系统而变化.

paintEvent的Qt文档仅说明

绘制事件是重新绘制全部或部分窗口小部件的请求.它可能由于以下原因之一而发生:

调用了repaint()或update(),

小部件被遮挡了,现在已被发现,或者

许多其他原因.

到目前为止,我在paintEvent中添加了一些痕迹,

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

这就是我发现的(至少在Windows 7上):

当窗口小部件失去/获得焦点时,将调用paintEvent.当另一个小部件通过我们的小部件时,不会调用 paint事件.我不知道是不是因为Windows 7合成.恢复最小化窗口时也会调用paintEvent.调整大小时调用paintEvent.

依赖于操作系统的行为是什么?

Cod*_*ray 19

是的,从您描述的意义上讲,它取决于操作系统.

桌面窗口管理器(DWM),在Windows Vista和7中找到,负责桌面组合的doohickey,Aero玻璃效果和各种其他眼睛糖果,与以前版本的Windows中使用的模型有点不同.正如您所怀疑的那样,它会缓存窗口的位图,即使它们不可见,因为它们被另一个窗口遮挡了.这意味着它不需要你重绘它们(因此它不会引发绘制事件),因为它只能从缓存的位图中将它们blit.这不仅是每个应用程序重绘自身的潜在优化,它还允许DWM实现Aero Flip之类的东西,它使用其缓存的位图.

例外情况就像它一直是CS_SAVEBITS类风格一样.如果DWM缓存的位图已失效(例如,因为您的窗口图像已更改),它将丢弃它并要求您重绘窗口.

通过关闭DWM组合(切换到"Windows Classic"主题)测试此理论,然后遮挡窗口以查看是否收到绘制事件.您应该像在所有以前版本的Windows中一样.

但更重要的是,您不应该依赖于以任何特定顺序接收油漆事件.应该承担约油漆事件的事情是,当操作系统需要你重新绘制你的窗口,你会收到一个.否则,它不会打扰你.我确信这就是为什么文档在这一点上含糊不清,超出可能的技术限制.

这就是逻辑不应该进入paint事件处理程序的原因.该方法唯一应该负责的是按当前状态重新绘制窗口.那个州需要在其他地方拯救.此规则也是可交换的:您不应在paint事件处理程序之外进行任何绘制.

当然,你总是可以通过使窗口无效来强制绘制一个绘制事件(我确定Qt有一个invalidate或者refresh方法,检查文档),但这并不意味着放置应用程序逻辑是一个很好的模式在处理此事件的方法中.