如何连接在PyQt4的控制器的信号? (iOS的像PyQt4中MVC结构)(How to con

2019-11-01 02:04发布

为什么不下面的例子中工作?

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结构(像在图4 -无模型),其中控制器( TestViewController )接收参考视图( TestView )和连接所述点击信号从视图的按钮view.btn到其功能self.buttonClicked

我敢肯定行view.btn.clicked.connect(self.buttonClicked)被执行,但是,很显然,它没有任何效果。 有谁知道如何解决呢?


更新(可怕的解决方案):

在这个例子中,如果我更换线

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

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

有用。 我还没有高兴。

Answer 1:

它不工作的原因是因为控制器类被垃圾收集你都不能点击任何东西之前。

当您设置view.clicked = self.clicked,视图对象上你实际上做的是使从控制器的一个对象持续存在,因此它永远不会被清理 - 这是不是真正的解决方案。

如果你的控制器存储到一个变量,它会保护它免受集合。

所以,如果你改变你上面的代码如下:

ctrl = TestViewController(view)

您将所有设置。

话虽这么说 - 正是你正在尝试做的,我不知道......看来你想建立一个MVC系统的Qt - Qt的,但已经有,使用Qt设计分开一个相当不错的系统界面组件到UI(视图/模板)文件从控制器逻辑(QWidget的子类)。 同样,我不知道你正在尝试做的,这可能是它的一个愚蠢的缩小版本,但是我建议你做它像这样所有一类:

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)
        self.btn.clicked.connect(self.buttonClicked)

    def buttonClicked(self):
        print 'clicked'

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

if __name__ == '__main__':
    main()

编辑:澄清的Qt的MVC

因此,这上面的例子中实际上并没有动态加载UI并创建一个控制器/视图的分离。 它有点难以这里展示上。 最好通过一些QT /设计师基于例子/教程工作-我这里有一台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()


文章来源: How to connect a signal from the controller in PyQt4? (iOS like MVC structure in PyQt4)