如何在PyQt4中从控制器连接信号?(类似iOS的MVC结构在PyQt4中)

2024-10-03 23:20:31 发布

您现在位置:Python中文网/ 问答频道 /正文

为什么下面的例子不起作用?在

from PyQt4 import QtGui
import sys

class TestView(QtGui.QWidget):

    def __init__(self):
        super(TestView, self).__init__()
        self.initUI()

    def initUI(self):
        self.btn = QtGui.QPushButton('Button', self)
        self.btn.resize(self.btn.sizeHint())
        self.btn.move(50, 50)

class TestViewController():

    def __init__(self, view):
        view.btn.clicked.connect(self.buttonClicked)
        view.show()

    def buttonClicked(self):
        print 'clicked'

def main():
    app = QtGui.QApplication(sys.argv)
    view = TestView()
    TestViewController(view)
    app.exec_()

if __name__ == '__main__':
    main()

这个例子应该表示一个MVC结构(类似于Figure 4中没有模型的结构),其中控制器(TestViewController)接收对视图(TestView)的引用,并将视图按钮view.btn的点击信号连接到其函数self.buttonClicked。在

我确信view.btn.clicked.connect(self.buttonClicked)行已执行,但显然,它没有任何效果。有人知道怎么解决这个问题吗?在


更新(糟糕的解决方案):

在示例中,如果我替换行

^{pr2}$

view.clicked = self.clicked
view.btn.clicked.connect(view.clicked)

它起作用了。我还是不满意。在


Tags: importselfviewinitmaindefconnectsys
1条回答
网友
1楼 · 发布于 2024-10-03 23:20:31

它不起作用的原因是,在您可以为它单击任何东西之前,控制器类正在被垃圾回收。在

当你准备好查看。单击= 自我点击,您实际上要做的是使控制器中的一个对象持久化在视图对象上,这样它就永远不会被清理掉——这不是真正的解决方案。在

如果您将控制器存储到变量,它将保护它不被收集。在

因此,如果您将上面的代码改为:

ctrl = TestViewController(view)

你会准备好的。在

也就是说-你到底想做什么,我不确定…似乎你在尝试为Qt设置一个MVC系统-但是Qt已经有了一个很好的系统,使用Qt设计器将接口组件从控制器逻辑(QWidget子类)中分离成UI(视图/模板)文件。再说一次,我不知道你想做什么,这可能是一个愚蠢的版本,但我建议你把它做成一个类,像这样:

^{pr2}$

编辑:澄清Qt的MVC

因此,上面的例子实际上并没有动态加载ui并创建控制器/视图分离。在这里表现有点难。最好学习一些基于Qt/Designer的示例/教程-我在这里有一个http://bitesofcode.blogspot.com/2011/10/introduction-to-designer.html,但是很多可以在网上找到。在

简单的回答是,loadUi方法可以替换为PyQt4.uic动态加载(有许多不同的方法来设置它),这样您的代码最终会读取如下内容:

from PyQt4 import QtGui
import PyQt4.uic
import sys

class TestController(QtGui.QWidget):

    def __init__(self):
        super(TestController, self).__init__()

        # load view
        uifile = '/path/to/some/widget.ui'
        PyQt4.uic.loadUi(uifile, self)

        # create connections (assuming there is a widget called 'btn' that is loaded)
        self.btn.clicked.connect(self.buttonClicked)

    def buttonClicked(self):
        print 'clicked'

def main():
    app = QtGui.QApplication(sys.argv)
    view = TestController()
    view.show()
    app.exec_()

if __name__ == '__main__':
    main()

编辑2:存储UI引用

如果更容易可视化此概念,还可以存储对生成的UI对象的引用:

from PyQt4 import QtGui
import PyQt4.uic
import sys

class TestController(QtGui.QWidget):

    def __init__(self):
        super(TestController, self).__init__()

        # load a view from an external template
        uifile = '/path/to/some/widget.ui'
        self.ui = PyQt4.uic.loadUi(uifile, self)

        # create connections (assuming there is a widget called 'btn' that is loaded)
        self.ui.btn.clicked.connect(self.buttonClicked)

    def buttonClicked(self):
        print 'clicked'

def main():
    app = QtGui.QApplication(sys.argv)
    view = TestController()
    view.show()
    app.exec_()

if __name__ == '__main__':
    main()

相关问题 更多 >