1

How to receive close event in following code?

class Main(QMainWindow):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.view = QUiLoader().load("sample.ui", self)
        self.view.show()

    def closeEvent(self, e):
        print "close event recieved"

def main():
    app = QApplication(sys.argv)
    a=Main()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

If I convert sample.ui to sample.py using pyside-uic and importing this into main.py then I was able to receive close event.

from sample import Ui_MainWindow

class Main(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.setupUi(self)

    def closeEvent(self, e):
        print "close event recieved"

app = QApplication(sys.argv)
a=Main()
a.show()
sys.exit(app.exec_())
Patrick
  • 2,464
  • 3
  • 30
  • 47

1 Answers1

4

The second example works because it effectively becomes a subclass of the top-level class from Qt Designer. By contrast, the first example uses composition rather than subclassing, which puts all the gui elements inside an internal namespace. The Main class is just a container that acts as the parent of the view widget, and is never actually shown (which in turn means it doesn't receive any close events).

In PyQt, the uic module has several funtions which allow you to work around these issues, but there is currently nothing like that in PySide. Instead, you have to roll your own function. See this answer for an explanation of how to do that.

Alternatively, you could change the top-level class in Qt Designer to a QWidget, and then make view the central widget of your Main class. This is a lot less flexible than the above method, though.

Community
  • 1
  • 1
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • If i take Widget form instead of MainWindow while designing UI file and replace self.view.show() with self.show() for 1st method and add self.setCentralWidget(self.view) above show(). Then i am able to receive close event. But don't know how ? – Patrick Apr 08 '15 at 17:43
  • @pythonlearner. Because you are showing `self` rather than `self.view`, and `self` has the `closeEvent` defined for it. – ekhumoro Apr 08 '15 at 17:53
  • but if i do self.show() in the 1st method of my post it shows an empty UI thatswhy i used self.view.show() – Patrick Apr 08 '15 at 18:06
  • so my doubt is how changing QMainWindow in UI file to QWidget is allowing me to show UI using self.view() ? – Patrick Apr 08 '15 at 18:21
  • @pythonlearner. I covered this in the second paragraph of my answer. PySide lacks the ability to load widgets into an instance like PyQt can. If you look at [my linked answer](http://stackoverflow.com/a/27610822/984421), you will find a work-around for PySide. – ekhumoro Apr 08 '15 at 18:23
  • Yeah i saw the workaround but i am interested in knowing how changing QMainWindow to QWidget is making difference ? – Patrick Apr 08 '15 at 18:27
  • 1
    @pythonlearner. You'd probably need to look at how PySide implements its `QUiLoader` class. For some reason, it treats `QMainWindow` and `QDialog` differently. If the second argument to `load` is an instance of one of those classes, it will become the *parent* of the returned widget. I don't know if that is what is actually intended, though - you'd have to ask the PySide devs about that. Maybe it's a bug? – ekhumoro Apr 08 '15 at 18:47