Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. QTabWidget.tabCloseRequested
Forum Updated to NodeBB v4.3 + New Features

QTabWidget.tabCloseRequested

Scheduled Pinned Locked Moved Solved Qt for Python
7 Posts 2 Posters 770 Views 1 Watching
  • 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.
  • MasterQM Offline
    MasterQM Offline
    MasterQ
    wrote on last edited by MasterQ
    #1

    Hi,

    my mainwindow (QWidget-Application) contains of a menu bar and a QTabWidget. The tabs of the tabWidget are created dynamically by clicking a menu item

        @Slot()
        def on_actionAges_triggered(self):
            tab = self.ui.tabWidget.findChild(AgesPage)
            if tab is None:
                tab = AgesPage(self.ui.tabWidget)
                self.ui.tabWidget.addTab(tab, "Ages")
            
            self.ui.tabWidget.setCurrentWidget(tab)
    

    and removed by

        @Slot(int)
        def on_tabWidget_tabCloseRequested(self, index) ->None:
            widget = self.ui.tabWidget.children()[index]        
            self.ui.tabWidget.removeTab(index)
            widget.deleteLater()
    

    The issue is that after the close event is finished (deleteLater) the whole application is crashing with SIGSEV.

    What's wrong with this approach? I do not want to keep a removed tab in memory.

    A simple removeTab keeps the tab in memory and also as a child of tabWidget but invisible. Then setting isVisible to true again brings it not back on screen. Maybe it is marked internally as deleted?

    How to remove/close a tab correctly?

    Joachim

    JonBJ 1 Reply Last reply
    0
    • MasterQM Offline
      MasterQM Offline
      MasterQ
      wrote on last edited by
      #6

      OK, light at the end of the tunnel!

      the line

      widget = self.ui.tabWidget.children()[index]
      

      must be replaced by

      widget = self.ui.tabWidget.widget(index)
      

      to get what I expect, widget is now of type AgesPage

      after removeTab(index) the tab can then not be found anymore in tabWidget.widget(index).

      The following is doing the job:

          @Slot(int)
          def on_tabWidget_tabCloseRequested(self, index) ->None:
              widget = self.ui.tabWidget.widget(index)
              self.ui.tabWidget.removeTab(index)
              widget.deleteLater()
      

      Oh dear, what a painful afternoon.

      JonBJ 1 Reply Last reply
      1
      • MasterQM MasterQ

        Hi,

        my mainwindow (QWidget-Application) contains of a menu bar and a QTabWidget. The tabs of the tabWidget are created dynamically by clicking a menu item

            @Slot()
            def on_actionAges_triggered(self):
                tab = self.ui.tabWidget.findChild(AgesPage)
                if tab is None:
                    tab = AgesPage(self.ui.tabWidget)
                    self.ui.tabWidget.addTab(tab, "Ages")
                
                self.ui.tabWidget.setCurrentWidget(tab)
        

        and removed by

            @Slot(int)
            def on_tabWidget_tabCloseRequested(self, index) ->None:
                widget = self.ui.tabWidget.children()[index]        
                self.ui.tabWidget.removeTab(index)
                widget.deleteLater()
        

        The issue is that after the close event is finished (deleteLater) the whole application is crashing with SIGSEV.

        What's wrong with this approach? I do not want to keep a removed tab in memory.

        A simple removeTab keeps the tab in memory and also as a child of tabWidget but invisible. Then setting isVisible to true again brings it not back on screen. Maybe it is marked internally as deleted?

        How to remove/close a tab correctly?

        Joachim

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

        @MasterQ said in QTabWidget.tabCloseRequested:

        A simple removeTab keeps the tab in memory and also as a child of tabWidget but invisible. Then setting isVisible to true again brings it not back on screen. Maybe it is marked internally as deleted?

        This surprises me, but you may be correct. You did not allocate a tab for addTab(), I don't see you're supposed to delete it. removeTab() should do the job or whatever is safe. Which seems to be what the crash is telling you. You may delete any tab widget/contents if you wish.

        If you were supposed to delete a removed tab, usual Qt would be for removeTab() to return (a pointer to) the thing to be deleted. It does not.

        Did you check what type widget = self.ui.tabWidget.children()[index] is, is it your AgesPage, I'm thinking not?

        I admit I am not sure of my ground on this, feel free to ignore me :)

        MasterQM 1 Reply Last reply
        0
        • JonBJ JonB

          @MasterQ said in QTabWidget.tabCloseRequested:

          A simple removeTab keeps the tab in memory and also as a child of tabWidget but invisible. Then setting isVisible to true again brings it not back on screen. Maybe it is marked internally as deleted?

          This surprises me, but you may be correct. You did not allocate a tab for addTab(), I don't see you're supposed to delete it. removeTab() should do the job or whatever is safe. Which seems to be what the crash is telling you. You may delete any tab widget/contents if you wish.

          If you were supposed to delete a removed tab, usual Qt would be for removeTab() to return (a pointer to) the thing to be deleted. It does not.

          Did you check what type widget = self.ui.tabWidget.children()[index] is, is it your AgesPage, I'm thinking not?

          I admit I am not sure of my ground on this, feel free to ignore me :)

          MasterQM Offline
          MasterQM Offline
          MasterQ
          wrote on last edited by
          #3

          @JonB said in QTabWidget.tabCloseRequested:

          @MasterQ said in QTabWidget.tabCloseRequested:

          A simple removeTab keeps the tab in memory and also as a child of tabWidget but invisible. Then setting isVisible to true again brings it not back on screen. Maybe it is marked internally as deleted?

          This surprises me, but you may be correct. You did not allocate a tab for addTab(),

          from the documentation it is not necessary to allocate a tab itself. It is sufficient to allocate the content of the tab as is done in the line

          tab = AgesPage(self.ui.tabWidget)
          

          Did you check what type widget = self.ui.tabWidget.children()[index] is, is it your AgesPage, I'm thinking not?

          widget here is of type QStackedWidget. ??

          I am confused:
          QTabWidget.findchild() finds different things as QTabWidget.children()[index]?

                  index = self.ui.tabWidget.indexOf(tab)
                  widget = self.ui.tabWidget.children()[index]
                  
                  self._logger.debug(f" findchild {tab} - children[] {widget}")
          

          gives

          2024-09-22 16:32:42,412 [DEBUG] __main__ (line 53):  findchild <agespage.AgesPage(0x55e9e88b01b0, name="AgesPage") at 0x7f85aaabf100> - children[] <PySide6.QtWidgets.QStackedWidget(0x55e9e87c9dd0, name="qt_tabwidget_stackedwidget") at 0x7f85aaaadbc0>
          

          makes this sense??

          OK, this maybe explains the crash. But it is still the case that after a simple

          index = tabWidget.findchild(AgesPage)
          tabWidget.RemoveTab(index)
          
          tabWidget.findchild(AgesPage)
          

          still finds a "child". This should be removed already, even if it is still present in memory until the garbage collection runs over it.

          1 Reply Last reply
          0
          • MasterQM Offline
            MasterQM Offline
            MasterQ
            wrote on last edited by
            #4
                    self.ui.tabWidget.removeTab(index)
                    self._logger.debug(f" still available {self.ui.tabWidget.findChild(AgesPage)}")
            
            2024-09-22 16:47:07,243 [DEBUG] __main__ (line 83):  still available <agespage.AgesPage(0x55fe2febb9b0, name="AgesPage") at 0x7faef1fc72c0>
            
            JonBJ 1 Reply Last reply
            0
            • MasterQM MasterQ
                      self.ui.tabWidget.removeTab(index)
                      self._logger.debug(f" still available {self.ui.tabWidget.findChild(AgesPage)}")
              
              2024-09-22 16:47:07,243 [DEBUG] __main__ (line 83):  still available <agespage.AgesPage(0x55fe2febb9b0, name="AgesPage") at 0x7faef1fc72c0>
              
              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #5

              @MasterQ

              widget here is of type QStackedWidget

              The internals of QTabWidget, which you should leave alone.

              tab = AgesPage(self.ui.tabWidget)
              

              You allocated it like this, so it is a child of self.ui.tabWidget. But it's not on a tab, or at least not on a visible one, any longer now that you have removed the tab.

              I wrote earlier:

              You may delete any tab widget/contents if you wish.

              You put a new AgesPage on a tab. You have removed that tab. The docs say you can delete the widget you put on the tab. Tabs are not "parents" or do not "own" the widget which is on them, in some sense.

              I don't think you should need to be poking around in a QTabWidget's children.

              1 Reply Last reply
              0
              • MasterQM Offline
                MasterQM Offline
                MasterQ
                wrote on last edited by
                #6

                OK, light at the end of the tunnel!

                the line

                widget = self.ui.tabWidget.children()[index]
                

                must be replaced by

                widget = self.ui.tabWidget.widget(index)
                

                to get what I expect, widget is now of type AgesPage

                after removeTab(index) the tab can then not be found anymore in tabWidget.widget(index).

                The following is doing the job:

                    @Slot(int)
                    def on_tabWidget_tabCloseRequested(self, index) ->None:
                        widget = self.ui.tabWidget.widget(index)
                        self.ui.tabWidget.removeTab(index)
                        widget.deleteLater()
                

                Oh dear, what a painful afternoon.

                JonBJ 1 Reply Last reply
                1
                • MasterQM MasterQ has marked this topic as solved on
                • MasterQM MasterQ

                  OK, light at the end of the tunnel!

                  the line

                  widget = self.ui.tabWidget.children()[index]
                  

                  must be replaced by

                  widget = self.ui.tabWidget.widget(index)
                  

                  to get what I expect, widget is now of type AgesPage

                  after removeTab(index) the tab can then not be found anymore in tabWidget.widget(index).

                  The following is doing the job:

                      @Slot(int)
                      def on_tabWidget_tabCloseRequested(self, index) ->None:
                          widget = self.ui.tabWidget.widget(index)
                          self.ui.tabWidget.removeTab(index)
                          widget.deleteLater()
                  

                  Oh dear, what a painful afternoon.

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

                  @MasterQ
                  Yes, that allows you to delete whatever widget is on the tab if you wish.
                  However, I don't think a tab has to have a widget, so to prevent error:

                      if widget is not None:
                          widget.deleteLater()
                  
                  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