【问题标题】:When does a Qt widget get a paintEvent?Qt 小部件何时获得paintEvent?
【发布时间】:2012-07-25 08:31:54
【问题描述】:

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

paintEvent 的 Qt 文档只说

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

repaint() 或 update() 被调用,

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

许多其他原因。

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

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

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

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

那么行为是否依赖于操作系统?

【问题讨论】:

    标签: c++ qt paintevent


    【解决方案1】:

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

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

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

    通过关闭 DWM 组合(切换到“Windows 经典”主题)来测试这个理论,然后遮盖您的窗口以查看您是否收到绘制事件。您应该,就像您在所有以前的 Windows 版本中所做的那样。

    但更重要的一点是,您不应依赖以任何特定顺序接收绘制事件。 唯一您应该假设的有关绘制事件的事情是,当操作系统需要您重新绘制窗口时,您会收到一个。否则,它不会打扰您。我确信这就是文档满足于在这一点上含糊其辞的原因,超出了可能的技术限制。

    这就是为什么逻辑不应该进入绘制事件处理程序内部的原因。 唯一该方法应该负责的事情是按其当前状态重新绘制窗口。该状态需要保存在其他地方。这条规则也是可交换的:您不应该在绘制事件处理程序之外进行任何绘制

    当然,您总是可以强制通过使窗口无效来引发绘制事件(我确信 Qt 有一个 invalidaterefresh 方法,请查看文档) ,但这并不意味着将应用程序逻辑放置在处理此事件的方法中是一种好的模式。

    【讨论】:

    • 另请注意,每当我们正在谈论的 QWidget 之上的另一个 QWidget 出现/消失/移动/调整大小时,就会发生重新绘制。至少这是默认行为。在这种情况下,调用paintEvent 时使用特定区域(QRegion)作为QPaintEvent 的参数,它描述了要更新的区域。使用这条信息可以优化重绘内容所需的步骤,但我认为这很少使用。
    猜你喜欢
    • 2015-04-09
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-17
    • 2017-03-03
    • 1970-01-01
    相关资源
    最近更新 更多