PyQt Child Widget没有收到paintEvent

发布于 2024-12-01 19:02:09 字数 3696 浏览 1 评论 0原文

我在 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"

现在,当我创建一个实例化 MyCanvas 的应用程序 Test 时(见下文),将调用 Test 的 PaintEvent,但从未调用 MyCanvcas 的 PaintEvent,不会绘制矩形,并且控制台上不会输出“Paintevent Canvas”。如果我在 Test.paintevent() 中调用 self.widget.update() 或 self.widget.redraw() ,则不会捕获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 中,该小部件将作为应用程序工作吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北恋 2024-12-08 19:02:09

在 Test 类中,您没有将布局附加到参数 Gui,而是将其作为参数传递给 QVBoxLayout,并且为 self.widget.setupUi 调用了 < code>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)

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文