Дочерний виджет PyQt не получает событие paintEvent

Я создал виджет в qt Designer и преобразовал файл ui с помощью pyuic в класс python под названием Ui_wid_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))

Из Ui_wid_canvas я создал класс MyCanvas для реализации функции paintEvent и некоторых вспомогательных функций, таких как moo (). Все, что нужно сделать в рамках мероприятия, - это нарисовать два прямоугольника. Если я использую следующий класс в качестве приложения, все работает как шарм.

# 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 (см. Ниже), вызывается событие paintEvent для Test, но событие paintevent для MyCanvcas никогда не вызывается, прямоугольники не рисуются и на консоли не выводится «Paintevent Canvas». Если я вызываю self.widget.update() или self.widget.redraw() в Test.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, но я хотел бы оставаться независимым от платформы.

Пожалуйста, извините, что опубликовал так много кода, но я думаю, это упростит задачу. Я старался свести его к минимуму. Может ли кто-нибудь сказать мне, как я могу нарисовать виджет MyCanvas на себе и включить этот виджет рисования в другой виджет MyTest, который будет работать как приложение?


person cledith    schedule 29.08.2011    source источник
comment
Где код класса MyCanvas?   -  person alexisdm    schedule 29.08.2011
comment
Извините, неверный код вставлен. Фиксированный.   -  person cledith    schedule 29.08.2011


Ответы (1)


В вашем классе Test вы не прикрепили макет к параметру Gui, передав его как параметр в QVBoxLayout, и вы вызвали self.widget.setupUi для MyCanvas, хотя он уже был вызван конструктором MyCanvas.

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)
person alexisdm    schedule 29.08.2011