QWidget更新事件但没有视觉更新。

6
在Mint Linux 12上使用Qt4.8,我实现了一个简单的窗口,包含一个QTableView来显示模型的内容。模型数据不断更新(日志消息),并且dataChanged()信号会定期发出(即每100ms)。
我看到的问题是表格上的视觉更新出现了卡顿。
我在窗口上安装了一个事件过滤器,用于计算updateRequest类型的事件数量,这应该会触发部件重绘(也包括子部件,即tableView)。这些事件之间的平均时间为约170毫秒,标准偏差为约90毫秒(我想这相当大)。然而,感知到的视觉更新速率只有每秒两三次,我想知道原因。似乎并不是所有的updateRequest事件都会触发部件重绘,或者窗口系统吞噬了视觉更新。
作为第二个测试,我强制窗口每100ms更新一次,方法是调用repaint或update。使用repaint,我看到updateRequest类型的事件数量相应增加,间隔的标准偏差减小;而使用update,则没有增加。但是,两种情况下感知到的更新速率只有适度增加。
此外:有没有一种好的方法可以测量部件实际上被重绘的频率,而不必超载其paintEvent处理程序?也许可以从QTest中找到一些方法?
更新:我扩展了我的事件过滤器,以便也捕获paintEvent类型的事件。其中只有个位数的这种事件,而updateRequest类型的事件则有超过1000个。
2个回答

1

您应该对事件调度程序的aboutToBlock()awake()信号进行仪器化,并使用QElapsedTimer测量它们之间的时间。当前线程的事件调度程序实例由静态QAbstractEventDispatcher::instance()返回。

如果事件循环在您的时间测量窗口的一小部分时间内休眠,这意味着GUI线程中有太多的事情要处理。您可以计算事件循环休眠的时间,例如,在最后一秒钟内。如果低于10%,则可以预期更新速度较慢等问题。请记住,更新事件使用Qt :: LowEventPriority排队。它们将被标准排队信号和几乎所有其他事件抢占。


好主意!目前我在项目方面的时间表很紧,所以需要几天时间来测试这个。我认为这应该能够给我一个很好的负载概述,但实际上我计算了到达我的小部件的updateRequest事件,它们比感知的更新速率更接近(平均而言)。 - arne
计数没问题,但它并不能告诉你任何关于潜在问题的信息。它只是告诉你有一个问题,而且,显然你可以不写一行代码就能注意到它 :) - Kuba hasn't forgotten Monica

0

QApplication::compressEvent 会丢弃 QEvent::UpdateRequest,如果已经有一个未处理的事件。因此,即使 repaint(s) 调用,如果事件被丢弃,则可以立即返回而不进行绘制。您可以通过覆盖 compressEvent 来检查是否丢弃了您的 updateRequest 事件。


我知道压缩的事情,但这不是在主事件循环/QApplication的某个地方完成的吗?我认为如果一个updateRequest到达一个小部件,这应该已经完成了。 - arne
你是对的,压缩是在EventLoop中完成的。我误解了你计算事件的地方。如果事件到达小部件,压缩已经完成了。所以,请忽略我的答案。 - Stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接