Search code examples
pythonqtpyside

How to accept close event of MainWindow when loading it with QUiLoader()?


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

Solution

  • 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.