QTabWidget.tabCloseRequested
-
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
-
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.
-
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
@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 yourAgesPage
, I'm thinking not?I admit I am not sure of my ground on this, feel free to ignore me :)
-
@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 yourAgesPage
, I'm thinking not?I admit I am not sure of my ground on this, feel free to ignore me :)
@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 yourAgesPage
, 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.
-
-
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>
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. -
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.
-
M MasterQ has marked this topic as solved on
-
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.