update()或者repaint()无法触发paintEvent()函数

19

我有一个QScrollArea,其中包含我的神奇滚动小部件。 我想在各种情况下更新其内容。

为此,我覆盖了paintEvent(QPaintEvent *)。 然后每次我想要它完成时,我在小部件上调用update()

问题: 这样paintEvent()永远不会被调用!

到目前为止,我尝试的故障排除方法:

  • 使用repaint()代替update()。应该立即调用它。不幸的是并没有成功。
  • 测试isVisible()updatesEnabled
  • 测试是否正确覆盖了函数。调整窗口大小会调用我的函数。只有我的手动update()、repaint()调用失败。
  • 实现一个QTimer,每500ms触发一次update()或repaint()。 触发器输出文本,但函数没有被调用。

有人有什么想法可以检查下一步吗? 什么可能导致repaint()不调用paintEvent()?


不是在QScrollArea上绘图,而是使用分配给它的QLabel解决了我的问题。我得到了QLabel的update()。 - ypnos
你能把你的头文件/类定义粘贴进来吗?你是否已经在里面加入了所有的Q_OBJECT宏?同时,可以简单描述一下你是如何重写paintEvent()函数的吗? - bgs
1个回答

32
解决方法是从您的QAbstractScrollArea派生类中调用this->viewport()->repaint()this->viewport()->update(),而不仅仅是调用repaint()update()
更多信息请参见Qt文档

QWidget * QAbstractScrollArea::viewport () const

返回视口小部件。 使用QScrollArea::widget()函数检索视口小部件的内容。

由于我们在QAbstractScrollArea派生类中拥有的内容将在视口小部件中显示,因此调用视口小部件的更新或重绘以再次绘制数据(调用我们的paintEvent)是有意义的。

基本上这是正确的答案。我的错误在于我从QScrollArea创建了自定义小部件,并认为我可以在那里进行个别绘制。相反,我应该重写视口的绘制函数,可能不太可能。 - ypnos
可以覆盖视口的绘图函数。在视口重新实现的paintEvent()中需要注意的是- 在创建QPainter对象时,不要像通常一样传递“this”指针,而是传递this->viewport()。使用QPainter(this->viewport())代替QPainter(this)。否则会抛出“QPainter is not active”错误。 - Abhiram
这适用于任何使用QAbstractScrollArea的“花哨”小部件,例如QTableWidget。非常感谢您指出这一点! - eresonance
这个问题我花了三个小时才解决。感谢您的发帖。 - darda
我不知道自己有多少次掉进了这个陷阱,尽管我应该知道得更好。似乎每年大约会写一个从QAbstractScrollArea派生的自定义小部件。这种情况很少发生,以至于我会忘记这个特定的事实,所以每次都会再次遇到这个问题。:( 我希望这个答案永远不会过时,并能提醒和帮助别人,更何况如果Qt已经修复了这个问题就更好了。或者有没有一种情况是故意调用QAbstractScrollArea::update()的呢? - Scheff's Cat

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