我在 qt 设计器中创建了一个小部件,并使用 pyuic 将 ui 文件转换为一个名为 Ui_wid_canvas 的 python 类。这应该用作特殊画布:
# file mgcanvas.py
from PyQt4 import QtCore, QtGui
class Ui_wid_canvas(object):
def setupUi(self, wid_canvas):
wid_canvas.setObjectName("wid_canvas")
wid_canvas.resize(400, 300)
self.horizontalLayout = QtGui.QHBoxLayout(wid_canvas)
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButton = QtGui.QPushButton(wid_canvas)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.retranslateUi(wid_canvas)
QtCore.QMetaObject.connectSlotsByName(wid_canvas)
def retranslateUi(self, wid_canvas):
wid_canvas.setWindowTitle(QtGui.QApplication.translate("wid_canvas", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("wid_canvas", "PushButton", None, QtGui.QApplication.UnicodeUTF8))
我从 Ui_wid_canvas 派生了一个 MyCanvas 类来实现 paintEvent 函数和一些实用函数,例如 moo()。在paintevent 中它所要做的就是绘制两个矩形。如果我使用以下类作为我的应用程序,那么一切都会像魅力一样。
# file mycanvas.py
from PyQt4 import QtCore, QtGui
import mgcanvas
class MyCanvas(mgcanvas.Ui_wid_canvas, QtGui.QWidget):
def __init__(self):
super(mgcanvas.Ui_wid_canvas, self).__init__()
self.setupUi(self)
def paintEvent(self, qpaintevent):
print "PaintEvent canvas"
painter = QtGui.QPainter(self)
painter.setBrush(QtGui.QColor(255,0,0,80))
painter.setPen(QtGui.QColor(00,00,00,255))
painter.drawRect(10,10,100,100)
r = QtCore.QRectF(110,110,100,100)
painter.drawRect(r)
painter.drawText(r,"Hello", QtGui.QTextOption(QtCore.Qt.AlignCenter))
def moo(self):
print "This is canvas mooing"
现在,当我创建一个应用程序 Test 实例化 MyCanvas(见下文)时,调用了 Test 的paintEvent,但从未调用过 MyCanvcas 的paintevent,没有绘制矩形,并且控制台上没有输出“Paintevent Canvas”。如果我调用self.widget.update()
或self.widget.redraw()
在 Test.paintevent() 中调用,则不会捕获到paintevent。如果我self.widget.paintevent()
手动调用,则调用该函数,但未激活画家。另一方面,显示了按钮,我认为该小部件已正确包含,但子小部件并未调用绘制事件。
# file test.py; executed with `python test.py`
from PyQt4 import QtCore, QtGui
import mycanvas
class Test(object):
def setupUi(self, Gui):
self.counter = 0
Gui.setObjectName("TestObject")
Gui.resize(500,500)
self.layout = QtGui.QVBoxLayout()
self.widget = mycanvas.MyCanvas()
self.widget.setupUi(self)
self.widget.setObjectName("wid_canvas")
self.layout.addWidget(self.widget)
self.retranslateUi(Gui)
QtCore.QMetaObject.connectSlotsByName(Gui)
def retranslateUi(self, Gui):
Gui.setWindowTitle(QtGui.QApplication.translate("TestObject", "Title", None, QtGui.QApplication.UnicodeUTF8))
def paintEvent(self, qpaintevent):
print "---> Enter"
self.counter += 1
print "counter", self.counter
self.widget.repaint()
self.widget.moo()
print "<-- Leave"
class MyTest(Test, QtGui.QWidget):
def __init__(self):
super(Test, self).__init__()
self.setupUi(self)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
ui = MyTest()
ui.show()
sys.exit(app.exec_())
设置 Qt.WA_PaintOutsidePaintEvent 不是一个选项,因为它不适用于 Mac 和 Windows,但我想保持平台独立。
请原谅我发布了这么多代码,但我想这会让事情变得更容易。我试图将其保持在最低限度。有人能告诉我如何让 Widget MyCanvas 在其自身上绘画并将这个绘画小部件包含在另一个小部件 MyTest 中,它将作为应用程序工作吗?