如何在调用更新时触发paintEvent?

时间:2013-09-13 02:53:17

标签: qt paintevent

众所周知,当小部件变得可见或基本窗口发生任何事件时,会自动触发QWidget::paintEvent。如果我只希望发出paintEvent以回复update(),该怎么办?

1 个答案:

答案 0 :(得分:0)

只要需要绘制小部件,就不会发出paintEvent是没有意义的。你要求这样一个选项的理由意味着你试图以一种不打算使用的方式使用Qt API。我无法想象一个特定的设计会引导你这样使用,抱歉。

所以,我唯一可以告诉你的是你如何使用update()。处理小部件更新的惯用方法如下:

  1. 更新窗口小部件使用的数据源。例如,更改影响可见内容的文本或某些变量。通常,此数据是窗口小部件的Q_PROPERTY。 setter函数正在更新存储值的成员变量并调用update()。 setter不应该执行任何昂贵的计算 - 它们应该推迟到绘制事件。

  2. 如果在事件循环有机会运行之前多次更改属性,则更新事件将合并。在内部,对update()的调用导致将事件发布到GUI线程的事件队列。如果给定窗口小部件的队列中已存在更新事件,则事件将合并。保留以下不变量:在任何给定时间,事件队列中的任何特定窗口小部件只能有一个更新事件。

  3. 当控件返回到事件循环时,更新事件将被调度到窗口小部件,最后调用您的QWidget::paintEvent(...)重新实现。此实现应该进行绘制窗口小部件所需的计算,并进行实际绘制。如果计算范围很广,则应将它们降级为工作线程。

  4. 实施例

    假设一个应用程序正在从串行端口接收数据,建模为QIODevice(一个QSerialPort是一个)。你可以这样做:

    1. QIODevice的{​​{1}}信号连接到解析器readyRead中的一个插槽。

    2. 插槽接收并解析数据。然后它发出具有已处理数据的信号(例如,浮点值向量)。此信号连接到小部件中的QObject插槽。

    3. newData插槽将数据按原样添加到队列中,并安排newData。如果您正在使用Qt的数据结构,或者您的数据类是在它们之后建模并使用隐式共享和写时复制,那么速度非常快。

    4. update()将所有数据集出列并绘制它们。 update()方法可以方便地滚动图表。