QGraphicsView 或 QWidget 完成绘制或渲染时是不是存在信号或事件?

Posted

技术标签:

【中文标题】QGraphicsView 或 QWidget 完成绘制或渲染时是不是存在信号或事件?【英文标题】:Does a signal or event exist for when a QGraphicsView or QWidget is done being painted or rendered?QGraphicsView 或 QWidget 完成绘制或渲染时是否存在信号或事件? 【发布时间】:2013-07-03 12:36:58 【问题描述】:

我正在尝试为应用程序计时,以查看加载一些信息和绘制图表需要多长时间。我的函数首先加载数据,然后绘制图表。

计时相当简单,它调用一个外部函数,该函数从某个日期开始获取毫秒。 问题是即使我在开始时设置 t1 并在我调用 draw 函数后立即设置 t2,t2 也会在 QGraphicsView 实际更新之前返回。 (我知道,为什么这应该是异步的,这是有道理的)

例如,当我加载一个大文件时,它会在我减去两个值后以 700 毫秒返回,但实际渲染直到几秒钟后才完成。

我浏览了整个网络并搜索了 Qt 文档。我可以找到大量关于自己更新小部件的信息,但没有关于渲染完成后触发的任何类型的信号或事件的信息。

即使是QGraphicsScene::changed 信号似乎也只会在下面的场景发生变化时触发,而不是在渲染完成并且用户可以看到变化时触发。

关于如何做到这一点的任何帮助?

【问题讨论】:

【参考方案1】:

QGraphicsView 或 QWidget 完成绘制或渲染时是否存在信号或事件?

据我所知,它不存在。 (寻找类似的东西)

用户可以看到更改

据我所知,Qt使用的是双缓冲,所以如果绘制完成,并不意味着用户可以看到变化。

关于如何做到这一点的任何帮助?

如果你想知道绘画什么时候完成,那么……

    您可以继承 QGraphicsScene 并实现自己的 drawItems、drawBackground 或 drawForeground。这并不简单(因为项目绘制算法很复杂),但您可以知道每个项目何时完成绘制。 您可以从paintEvent(基于QWidget 的类)或paint()(基于QGraphicsItem/QGraphicsObject 的类)中发射/发射信号。显然,您需要使用自己的类,并且您必须将 QGraphicsView 或您在视图中绘制的项目或 QGraphicsScene 子类化。 您还可以创建代理 QPainter 类,这样您就可以知道具体是什么时候绘制的。

话虽如此,我怀疑您处理问题的方式不正确。

    如果您只是想绘制图表,那么您没有理由知道绘制何时完成。 绘制完成并不代表用户可以看到效果。 可能会多次调用绘画事件。

推荐方法:

使用线程或计时器事件从外部源接收/读取数据(您正在图表中绘制)(显然,如果您使用计时器事件,则需要以小块的形式读取数据),然后更新不时绘制图表,并让 Qt 处理重绘。


这究竟是如何让我检测从我选择打开文件到加载所有数据并绘制图表并可见所花费的时间?

    您可以通过子类化您用于绘制 Graph 的任何小部件、覆盖paintEvent 并从paintEvent 中触发信号、调用子例程或执行任何您想做的事情来检测paintEvent 何时完成绘制。 不保证paintEvent 只会被调用一次。 要测量单个例程有多慢并定位瓶颈,请使用分析器。 VerySleepy、AQTime 等。 与其测量加载和显示数据所需的时间,不如分别测量加载时间和显示时间更有意义。这是一个 GUI 应用程序,而不是游戏引擎,因此您无法精确控制何时绘制某些东西。

【讨论】:

这如何让我检测从打开文件到加载数据并绘制图表并可见所花费的时间?或者你是在暗示这是不可能的?我想你是说每隔一段时间加载文件的一小部分(并逐步更新图表),所以当它完全加载时,我知道已经过了多少间隔。如果那是错误的,我不明白你的答案。不过,这似乎不是正确的方法,因为我不想定义加载需要多长时间,我想知道它自己需要多长时间。【参考方案2】:

我没有测试它,但我认为通过继承 QGraphicsScene 并重新实现 render 方法,您可以测量渲染时间。

#include <QGraphicsScene>
#include <QTime>

class MyGraphicsScene : public QGraphicsScene 

Q_OBJECT
public:
void render ( QPainter * painter, const QRectF & target = QRectF(), const QRectF & source = QRectF(), Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio ) 
   QTime t;
   t.start();
   QGraphicsScene::render (painter, target, source, aspectRatioMode);
   qDebug("render time %d msec", t.elapsed());

;

【讨论】:

你不能重新实现它,它不是虚拟的。

以上是关于QGraphicsView 或 QWidget 完成绘制或渲染时是不是存在信号或事件?的主要内容,如果未能解决你的问题,请参考以下文章

QGraphicsView图像缩放

Qt:在 QGraphicsView/QGraphicsScene 上有一个孩子的 QWidget 不工作

QGraphicsView noobie 问题

QGraphicsScene Event::widget() 总是 QGraphicsView 吗?

如何从主 QWidget 中移除 QGraphicsTextItem 的焦点

如何从 QGraphicsScene/QGraphicsView 创建图像文件?