質問

I created a widget in qt designer and transformed the ui file using pyuic to a python class called Ui_wid_canvas. This is supposed to be used as special canvas:

# 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))

From Ui_wid_canvas I derive a class MyCanvas to implement the paintEvent function and some utility functions such as moo(). Within the paintevent all it shall do is draw two rects. If I use the following class as my application everything works like a charm.

# 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"

Now, when I create an application Test instantiating MyCanvas (see below), the paintEvent for Test is called, but the paintevent for MyCanvcas is never called, the rects are not drawn and no output "Paintevent Canvas" on the console. If I call self.widget.update() or self.widget.redraw() in Test.paintevent() the paintevent is not caught. If I call self.widget.paintevent() manually, the function is called, but the painter not activated. The pushbutton, on the other hand, is shown from which I figure that the widget is included correctly, but just not the paint event is called by the child widget.

    # 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_())

Setting the Qt.WA_PaintOutsidePaintEvent is not an option, because it does not work on Mac and Windows but I'd like to stay platform independent.

Please excuse me posting so much code, but I guess it will make things easier. I tried to keep it to a minimum. Can someone tell me how I can have the Widget MyCanvas paint on itself and include this painting widget in another widget MyTest, which will work as the application?

役に立ちましたか?

解決

In you class Test, you didn't attach the layout to the parameter Gui, by passing it as parameter to QVBoxLayout, and you called the self.widget.setupUi for MyCanvas although it was already called by MyCanvas constructor.

class Test(object):
    def setupUi(self, Gui):
        self.counter = 0
        Gui.setObjectName("TestObject")
        Gui.resize(500,500)
        self.layout = QtGui.QVBoxLayout(Gui)
        self.widget = mycanvas.MyCanvas()
        self.widget.setObjectName("wid_canvas")
        self.layout.addWidget(self.widget)

        self.retranslateUi(Gui)
        QtCore.QMetaObject.connectSlotsByName(Gui)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top