Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Handling Close Event in PyQt5 with QStackedWidget
Forum Updated to NodeBB v4.3 + New Features

Handling Close Event in PyQt5 with QStackedWidget

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 3 Posters 2.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    codingIsSoHard
    wrote on last edited by
    #1

    Hello everyone,

    I'm currently working on a PyQt5 project and encountered a challenge with handling the close event. I'm a beginner in PyQt5 and have successfully used the closeEvent method in a simple application to remind users to save their modifications when clicking the X button in the upper right corner. Here's a simplified example:

    class MainWindow(QWidget):
        def __init__(self):
            super().__init__()
    
        def closeEvent(self, event):
            print("close!")
            
    if __name__ == "__main__":
        app = QApplication(sys.argv)
    
        demo = MainWindow()
        demo.show()
    
        sys.exit(app.exec_())
    

    Now, I'm extending my project with two widgets using a QStackedWidget to switch between them:

    MAINWINDOW_INDEX = 1
    LOGINWINDOW_INDEX = 0
    
    class MainWindow(QWidget):
        def __init__(self, widget):
            super().__init__()
            self.widget = widget
    
        def closeEvent(self, event):
            print("close!")
    
    class LoginWindow(QWidget):
        def __init__(self, widget):
            super().__init__()
            button = QPushButton("goto main window", self)
            button.clicked.connect(self.onNewButtonClicked)
            self.widget = widget
    
        def onNewButtonClicked(self):
            mainwindow = MainWindow(self.widget)
            self.widget.addWidget(mainwindow)
            self.widget.setCurrentIndex(MAINWINDOW_INDEX)
    
        def closeEvent(self, event):
            print("close!")
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
    
        widget = QStackedWidget()
        loginwindow = LoginWindow(widget)
        
        widget.addWidget(loginwindow)
    
        widget.setFixedHeight(600)
        widget.setFixedWidth(450)
    
        widget.show()
    
        sys.exit(app.exec_())
    

    However, after this modification, the closeEvent in both functions is not being called when clicking on the X in the upper right corner. I suspect this may be due to the closeEvent that I need to override being in my QStackedWidget. How can I resolve this issue and ensure that the user is prompted to save their modifications when exiting the application? All of the data that needs to be saved is in mainwindow.

    I appreciate any guidance or solutions you can provide. Thanks in advance!

    jsulmJ JonBJ 2 Replies Last reply
    0
    • C codingIsSoHard

      Hello everyone,

      I'm currently working on a PyQt5 project and encountered a challenge with handling the close event. I'm a beginner in PyQt5 and have successfully used the closeEvent method in a simple application to remind users to save their modifications when clicking the X button in the upper right corner. Here's a simplified example:

      class MainWindow(QWidget):
          def __init__(self):
              super().__init__()
      
          def closeEvent(self, event):
              print("close!")
              
      if __name__ == "__main__":
          app = QApplication(sys.argv)
      
          demo = MainWindow()
          demo.show()
      
          sys.exit(app.exec_())
      

      Now, I'm extending my project with two widgets using a QStackedWidget to switch between them:

      MAINWINDOW_INDEX = 1
      LOGINWINDOW_INDEX = 0
      
      class MainWindow(QWidget):
          def __init__(self, widget):
              super().__init__()
              self.widget = widget
      
          def closeEvent(self, event):
              print("close!")
      
      class LoginWindow(QWidget):
          def __init__(self, widget):
              super().__init__()
              button = QPushButton("goto main window", self)
              button.clicked.connect(self.onNewButtonClicked)
              self.widget = widget
      
          def onNewButtonClicked(self):
              mainwindow = MainWindow(self.widget)
              self.widget.addWidget(mainwindow)
              self.widget.setCurrentIndex(MAINWINDOW_INDEX)
      
          def closeEvent(self, event):
              print("close!")
      
      if __name__ == "__main__":
          app = QApplication(sys.argv)
      
          widget = QStackedWidget()
          loginwindow = LoginWindow(widget)
          
          widget.addWidget(loginwindow)
      
          widget.setFixedHeight(600)
          widget.setFixedWidth(450)
      
          widget.show()
      
          sys.exit(app.exec_())
      

      However, after this modification, the closeEvent in both functions is not being called when clicking on the X in the upper right corner. I suspect this may be due to the closeEvent that I need to override being in my QStackedWidget. How can I resolve this issue and ensure that the user is prompted to save their modifications when exiting the application? All of the data that needs to be saved is in mainwindow.

      I appreciate any guidance or solutions you can provide. Thanks in advance!

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @codingIsSoHard said in Handling Close Event in PyQt5 with QStackedWidget:

      All of the data that needs to be saved is in mainwindow

      Then it should be enough to handle closeEvent in mainWindow, why do you need close events in other widgets?

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      C 1 Reply Last reply
      1
      • C codingIsSoHard

        Hello everyone,

        I'm currently working on a PyQt5 project and encountered a challenge with handling the close event. I'm a beginner in PyQt5 and have successfully used the closeEvent method in a simple application to remind users to save their modifications when clicking the X button in the upper right corner. Here's a simplified example:

        class MainWindow(QWidget):
            def __init__(self):
                super().__init__()
        
            def closeEvent(self, event):
                print("close!")
                
        if __name__ == "__main__":
            app = QApplication(sys.argv)
        
            demo = MainWindow()
            demo.show()
        
            sys.exit(app.exec_())
        

        Now, I'm extending my project with two widgets using a QStackedWidget to switch between them:

        MAINWINDOW_INDEX = 1
        LOGINWINDOW_INDEX = 0
        
        class MainWindow(QWidget):
            def __init__(self, widget):
                super().__init__()
                self.widget = widget
        
            def closeEvent(self, event):
                print("close!")
        
        class LoginWindow(QWidget):
            def __init__(self, widget):
                super().__init__()
                button = QPushButton("goto main window", self)
                button.clicked.connect(self.onNewButtonClicked)
                self.widget = widget
        
            def onNewButtonClicked(self):
                mainwindow = MainWindow(self.widget)
                self.widget.addWidget(mainwindow)
                self.widget.setCurrentIndex(MAINWINDOW_INDEX)
        
            def closeEvent(self, event):
                print("close!")
        
        if __name__ == "__main__":
            app = QApplication(sys.argv)
        
            widget = QStackedWidget()
            loginwindow = LoginWindow(widget)
            
            widget.addWidget(loginwindow)
        
            widget.setFixedHeight(600)
            widget.setFixedWidth(450)
        
            widget.show()
        
            sys.exit(app.exec_())
        

        However, after this modification, the closeEvent in both functions is not being called when clicking on the X in the upper right corner. I suspect this may be due to the closeEvent that I need to override being in my QStackedWidget. How can I resolve this issue and ensure that the user is prompted to save their modifications when exiting the application? All of the data that needs to be saved is in mainwindow.

        I appreciate any guidance or solutions you can provide. Thanks in advance!

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @codingIsSoHard said in Handling Close Event in PyQt5 with QStackedWidget:

        However, after this modification, the closeEvent in both functions is not being called when clicking on the X in the upper right corner. I suspect this may be due to the closeEvent that I need to override being in my QStackedWidget

        It does indeed appear that once you have a QStackedWidget it receives any closeEvent() (from the window's X close box), and that is not delivered to any widgets on the stack (when current/open or not). You can verify by subclassing QStackedWidget:

        class MyStackedWidget(QStackedWidget):
            def closeEvent(self, event):
                print("close MyStackedWidget!")
        

        So do the subclass and, perhaps, have it go through all child widgets/windows calling close() on them

        class MyStackedWidget(QStackedWidget):
            def closeEvent(self, event):
                print("close MyStackedWidget!")
                for i in range(self.count()):
                    widget = self.widget(i)
                    if widget:
                        widget.close()
        

        Or at least on any MainWindow instance (type(widget) is MainWindow or isinstance(widget, MainWindow)) if not all.

        P.S.
        Additionally, you might not choose to use any QStackedWidget for this use case of swapping between a logon window and a main window. Especially if this is a "once-only" operation, i.e. you do not allow the user to "log off" and then be re-presented with the logon page. You might just have them as separate, unconnected windows with show/hide/open/close instead. (In that case, be careful to show() the new window before you hide()/close() the existing one, else by default Qt will close your application when the first and only visible window gets closed, before the other one gets opened.)

        C 1 Reply Last reply
        1
        • jsulmJ jsulm

          @codingIsSoHard said in Handling Close Event in PyQt5 with QStackedWidget:

          All of the data that needs to be saved is in mainwindow

          Then it should be enough to handle closeEvent in mainWindow, why do you need close events in other widgets?

          C Offline
          C Offline
          codingIsSoHard
          wrote on last edited by
          #4

          @jsulm You are correct; only the mainWindow needs to be saved. I was just testing whether a closeEvent would be called at all. I apologize for any confusion.

          1 Reply Last reply
          0
          • C codingIsSoHard has marked this topic as solved on
          • JonBJ JonB

            @codingIsSoHard said in Handling Close Event in PyQt5 with QStackedWidget:

            However, after this modification, the closeEvent in both functions is not being called when clicking on the X in the upper right corner. I suspect this may be due to the closeEvent that I need to override being in my QStackedWidget

            It does indeed appear that once you have a QStackedWidget it receives any closeEvent() (from the window's X close box), and that is not delivered to any widgets on the stack (when current/open or not). You can verify by subclassing QStackedWidget:

            class MyStackedWidget(QStackedWidget):
                def closeEvent(self, event):
                    print("close MyStackedWidget!")
            

            So do the subclass and, perhaps, have it go through all child widgets/windows calling close() on them

            class MyStackedWidget(QStackedWidget):
                def closeEvent(self, event):
                    print("close MyStackedWidget!")
                    for i in range(self.count()):
                        widget = self.widget(i)
                        if widget:
                            widget.close()
            

            Or at least on any MainWindow instance (type(widget) is MainWindow or isinstance(widget, MainWindow)) if not all.

            P.S.
            Additionally, you might not choose to use any QStackedWidget for this use case of swapping between a logon window and a main window. Especially if this is a "once-only" operation, i.e. you do not allow the user to "log off" and then be re-presented with the logon page. You might just have them as separate, unconnected windows with show/hide/open/close instead. (In that case, be careful to show() the new window before you hide()/close() the existing one, else by default Qt will close your application when the first and only visible window gets closed, before the other one gets opened.)

            C Offline
            C Offline
            codingIsSoHard
            wrote on last edited by
            #5

            @JonB
            Thank you for your response. Everything appears to be functioning correctly after making the code modifications based on your suggestions. Also, thank you for your comments; I will reconsider whether it's possible to modify my program structure without using QStackedWidget. Wishing you a wonderful day!

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved