Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Override closeEvent with multiple window instances



  • I'm using qt designer to create the ui files, then pyuic to create the ui .py file and another file to handle them for every ui file. Basiclly something like this:
    main executable file:

    #!/usr/bin/env python3
    import mainwindow
    
    if __name__ == "__main__":
        import sys
        sys.exit(mainwindow.run())
    

    mainwindow_ui.ui (created in qt designer)
    mainwindow_ui.py (from pyuic)
    and
    mainwindow.py:

    from mainwindow_ui import Ui_MainWindow
    
    class MainWindow(QMainWindow, Ui_MainWindow):
        def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
                self.setupUi(self)
        ....
    def run():
        app = QtWidgets.QApplication(sys.argv)
        app.setQuitOnLastWindowClosed(True)
        ui = MainWindow()
        ui.show()
            return app.exec()
    

    With above I create and show the mainwindow.
    In my current project(a text editor) I have a method, which creates a new window instance like this:

        def new(self):
            self.update_title()
            self.ui=Notepad()
            self.ui.show()
    

    Notepad is the name of mainwindow

    I have also override the closeEvent to open a message dialog with save, cancel, close buttons:

        def closeEvent(self, event):
            event.ignore()
            self.confirmDlg()
    

    The buttons of confirmDlg() dialog:

                if box.clickedButton() == btnS:
                    self.save()
                    self.parent.close()
                elif box.clickedButton() == btnCl:
                    self.parent.close()
                elif box.clickedButton() == btnC:
                    box.close()
                    print("Canceled ")
    

    The problem is that I want to close only the current Notepad instance and not all instances of notepad, when I press the button of dialog. The above code is wrong and gives the error:

    self.parent.close()
    AttributeError: 'builtin_function_or_method' object has no attribute 'close'
    

    So, how to access to the current Notepad instance and close it from dialog's button, and don't close all instances?


  • Qt Champions 2019

    @dancaer69 said in Override closeEvent with multiple window instances:

    I have also override the closeEvent

    In which class?

    Why do you call self.parent.close()?



  • The mainwindow has one class with name Notepad.
    The confirmDlg() is a method inside this class. It's a QMessageBox in which I just have rename the standard buttons.
    About self.parent.close(), I just trying things. Because self.close() closes the dialog itself, I tried the parent because I thought(obviously wrong), that with this I will access the Notepad window instance.


  • Qt Champions 2019

    @dancaer69 You did not answer the question about closeEvent. So, in which class did you override it?
    Also, parent is a method. The error message already suggests that.

    self.parent().close()
    


  • The closeEvent method is inside Notepad class. I use it to prevent the default behaviour when click on window' s 'X' button. I think that the class is the Ui_Notepad which is the class in notepad_ui.py file which generated from the qt designer' s notepad_ui.ui file.



  • After some search about this I've made some changes from info I collected from different sources. I don't fully understand them all but with these changes seems that it works.
    First I changed the "new" method:

    def new(self)
        self.update_title()
        self.ui=Notepad()
        self.ui.show()
        widgetList.append(self.ui)
    

    Then I added a wigetList variable and append the opened windows in "run' and "new" methods.:

    def run():
        app = QtWidgets.QApplication(sys.argv)
        app.setQuitOnLastWindowClosed(True)
        ui = Notepad()
        if len(app.arguments())>1:
            filename = app.arguments()[1]
            if filename!=None:
                fileContent = open(filename, 'r', encoding=ui.detEnc(filename)).read()
                ui.teEditor.setText(fileContent)
        ui.show()
        widgetList.append(ui)
        return app.exec()
    

    I think that the change of "new" method made possible to close one window when press "X" button and not all.
    Because I couldn't close the window from confirmDlg method, I created a variable "self.reply", and I changed the confirmDlg' s buttons if condition and the closeEvent method:

                if box.clickedButton() == btnS:
                    self.save()
                elif box.clickedButton() == btnCl:
                    pass
                elif box.clickedButton() == btnC:
                    self.reply="cancel"
                    box.close()
                    print("Canceled "))
    

    and in closeEvent:

        def closeEvent(self, event):
            if self.teEditor.toPlainText()!="":
                event.ignore()
                self.confirmDlg()
                if self.reply!="cancel":
                    event.accept()
            else:
                event.accept()
    And with this I can close the window from "save" or "close" dialog's buttons only. 
    

Log in to reply