在 PyQt5 和 PySide2 中覆盖paintEvent
Posted
技术标签:
【中文标题】在 PyQt5 和 PySide2 中覆盖paintEvent【英文标题】:Overriding paintEvent in PyQt5 and PySide2 【发布时间】:2018-10-30 20:01:45 【问题描述】:我使用 PyQt 和 PySide 已经有一段时间了。今天我偶然发现了一个奇怪的行为:重新实现paintEvent似乎不适用于Qt5的Python版本。我在 Qt4 中从来没有遇到过这个问题。
from PySide2 import QtWidgets, QtCore, QtGui # use pyside
# from PyQt5 import QtWidgets, QtCore, QtGui # use pyqt
import sys
class TagWidget(QtWidgets.QWidget):
def __init__(self, parent):
super().__init__(parent)
print("__init__")
def paintEvent(self, e):
# this is called or not
# depends (see below)
print("paintEvent")
raise(AssertionError)
class MyGui(QtWidgets.QMainWindow):
def __init__(self,parent=None):
super(MyGui, self).__init__()
self.setupUi()
def setupUi(self):
self.setGeometry(QtCore.QRect(100,100,500,500))
self.w=QtWidgets.QWidget(self)
self.setCentralWidget(self.w)
self.lay = QtWidgets.QHBoxLayout(self.w)
self.image = TagWidget(self.w)
self.lay.addWidget(self.image)
# return
# exit here, and TagWidget.paintEvent
# is still being called
self.file_list = QtWidgets.QListWidget(self.w)
# return
# exit here, and TagWidget.paintEvent
# is still being called
self.lay.addWidget(self.file_list)
# .. but if we reach all the way here,
# TagWidget.paintEvent is never called !
def main():
app=QtWidgets.QApplication(["test_app"])
mg=MyGui()
mg.show()
app.exec_()
if (__name__=="__main__"):
main()
所以,我们只是在测试是否调用了paintEvent(通过在调用时引发 AssertionError)。
一旦我们将另一个小部件添加到 TagWidget 所在的同一布局中,paintEvent 就不再有效。
太奇怪了。帮助表示赞赏。
【问题讨论】:
【参考方案1】:paintEvent()
在需要重新绘制时被调用,如果小部件有size(0, 0)
,或者尺寸无效或被隐藏,则不会调用该方法,这就是你的情况,当使用布局时它会默认取sizeHint()
的大小,默认一个QWidgetsizeHint()
是QSize(-1, -1)
,因此不需要绘制。
所以解决办法是设置一个合适的sizeHint()
:
class TagWidget(QtWidgets.QWidget):
def paintEvent(self, e):
print("paintEvent")
raise(AssertionError)
def sizeHint(self):
print("default sizeHint: ", super(TagWidget, self).sizeHint())
return QtCore.QSize(640, 480)
我已经用PyQt4
和PySide
尝试过,同样的问题发生了,所以问题不在于Qt,而在于具体的例子。
【讨论】:
以上是关于在 PyQt5 和 PySide2 中覆盖paintEvent的主要内容,如果未能解决你的问题,请参考以下文章
QTableView 在 PyQt5/PySide2 中的每个选择上加载数据时锁定主窗体 [重复]
了解不一致的 cythonized 代码行为 - PyQt5 与 PySide2