Moving child widgets between QTabWidgets?

David Boddie david at boddie.org.uk
Wed Jan 18 17:12:12 GMT 2023


On Wed Jan 18 16:34:48 GMT 2023, Matic Kukovec wrote:

> removeTab() does not reparent the widget, you need to call setParent(None)
> after removeTab. That is exactly what I do not want, as setParent(None)
> will delete the underlying widget. I want it moved to the other tabwidget. 

At a high level, what are you trying to do?

In your original code, you first collect a list of widgets from the old tab
widget:

        def switch(self, *args):
            widgets = []
            old_tab_widget = self.tab_widget
            for i in reversed(range(old_tab_widget.count())):
                widgets.append((old_tab_widget.widget(i), 
old_tab_widget.tabText(i)))
                old_tab_widget.removeTab(i)

Then you reparent all the widgets in the window itself, including the old tab
widget:

            for i in reversed(range(self.centralWidget().count())):
                self.centralWidget().widget(i).setParent(None)

Then you discard references to the old tab widget, causing it to be deleted:

            old_tab_widget = None
            self.tab_widget = None

I think that this causes problems because I think the widgets you removed from
the tab widget still have a parent in the tab widget hierarchy and Qt may
still have ownership, so it just deletes the widgets behind your back.

Now you create a new tab widget and add the widgets again before adding the
tab widget to the window:

            new_tab_widget = QTabWidget()
            for widget, tab_text in widgets:
                new_tab_widget.addTab(widget, tab_text) # <- ERROR THROWN HERE

            self.centralWidget().addWidget(new_tab_widget)
            self.tab_widget = new_tab_widget


Here's another version of your original code with two lines added to reparent
the pages to None, so Python should take ownership of them:

    def switch(self, *args):
        widgets = []
        old_tab_widget = self.tab_widget
        for i in reversed(range(old_tab_widget.count())):
            widgets.append((old_tab_widget.widget(i), 
old_tab_widget.tabText(i)))
            w = old_tab_widget.widget(i)
            old_tab_widget.removeTab(i)
            w.setParent(None)

        for i in reversed(range(self.centralWidget().count())):
            self.centralWidget().widget(i).setParent(None)
        old_tab_widget = None
        self.tab_widget = None

        new_tab_widget = QTabWidget()
        for widget, tab_text in widgets:
            new_tab_widget.addTab(widget, tab_text) # <- ERROR THROWN HERE

        self.centralWidget().addWidget(new_tab_widget)
        self.tab_widget = new_tab_widget

Does this do what you want?

David


More information about the PyQt mailing list