Skip to content Skip to sidebar Skip to footer

How To Connect A Signal From The Controller In Pyqt4? (ios Like Mvc Structure In Pyqt4)

Why doesn't the following example work? from PyQt4 import QtGui import sys class TestView(QtGui.QWidget): def __init__(self): super(TestView, self).__init__()

Solution 1:

The reason it is not working is because the controller class is being garbage collected before you can ever click anything for it.

When you set view.clicked = self.clicked, what you're actually doing is making one of the objects from the controller persist on the view object so it never gets cleaned up - which isn't really the solution.

If you store your controller to a variable, it will protect it from collection.

So if you change your code above to read:

ctrl = TestViewController(view)

You'll be all set.

That being said - what exactly you are trying to do here, I am not sure...it seems you're trying to setup an MVC system for Qt - but Qt already has a pretty good system for that using the Qt Designer to separate the interface components into UI (view/template) files from controller logic (QWidget subclasses). Again, I don't know what you are trying to do and this may be a dumb down version of it, but I'd recommend making it all one class like so:

from PyQt4 import QtGui
import sys

classTestView(QtGui.QWidget):

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

    definitUI(self):
        self.btn = QtGui.QPushButton('Button', self)
        self.btn.resize(self.btn.sizeHint())
        self.btn.move(50, 50)
        self.btn.clicked.connect(self.buttonClicked)

    defbuttonClicked(self):
        print'clicked'defmain():
    app = QtGui.QApplication(sys.argv)
    view = TestView()
    view.show()
    app.exec_()

if __name__ == '__main__':
    main()

Edit: Clarifying the MVC of Qt

So this above example doesn't actually load the ui dynamically and create a controller/view separation. Its a bit hard to show on here. Best to work through some Qt/Designer based examples/tutorials - I have one here http://bitesofcode.blogspot.com/2011/10/introduction-to-designer.html but many can be found online.

The short answer is, your loadUi method can be replace with a PyQt4.uic dynamic load (and there are a number of different ways to set that up) such that your code ultimately reads something like this:

from PyQt4 import QtGui
import PyQt4.uic
import sys

classTestController(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)

    defbuttonClicked(self):
        print'clicked'defmain():
    app = QtGui.QApplication(sys.argv)
    view = TestController()
    view.show()
    app.exec_()

if __name__ == '__main__':
    main()

Edit 2: Storing UI references

If it is easier to visualize this concept, you Can also store a reference to the generated UI object:

from PyQt4 import QtGui
import PyQt4.uic
import sys

classTestController(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)

    defbuttonClicked(self):
        print'clicked'defmain():
    app = QtGui.QApplication(sys.argv)
    view = TestController()
    view.show()
    app.exec_()

if __name__ == '__main__':
    main()

Post a Comment for "How To Connect A Signal From The Controller In Pyqt4? (ios Like Mvc Structure In Pyqt4)"