I am dynamically creating multiple tabs, and I was wondering if when I close the tab, does it actually destroy the object?
I have set the attribute of the dynamically created tab to QtCore.Qt.WA_DeleteOnClose
I assume that setting the attribute doesn't do anything because the closeEvent isn't called on it.
self.tabWidget.tabCloseRequested.connect(self.close_handler) # connect close button to slot
def close_handler(self, index):
'Remove added tab if applicable'
try:
#self.tabWidget.widget(index).deleteLater() #does this need to be added?
self.tabWidget.removeTab(index)
except:
Data.logger.exception('Exception occured:')
How do I make sure that the object is being destroyed?
My answer is oriented to explain details that the other answer does not indicate so that you understand how it handles the memory Qt.
If you want to know if a QObject is eliminated then you must use the destroyed
signal.
If you want to delete a QObject you must use the deleteLater() method.
In the case of the elimination of a widget added to the QTabWidget this will notify the QTabBar that it will be deleted so there are no problems of accessing non-reserved memory.
Considering the above, a possible solution is:
def close_handler(self, index):
widget = self.tabWidget.widget(index)
widget.deleteLater()
You can check it with the following example:
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tabWidget = QtWidgets.QTabWidget(tabsClosable=True)
self.tabWidget.tabCloseRequested.connect(self.onTabCloseRequested)
self.setCentralWidget(self.tabWidget)
for i in range(10):
widget = QtWidgets.QWidget()
widget.destroyed.connect(
lambda obj: print(
"deleted {}, count: {}".format(obj, self.tabWidget.count())
)
)
self.tabWidget.addTab(widget, "Tab %s" % (i))
@QtCore.pyqtSlot(int)
def onTabCloseRequested(self, index):
widget = self.tabWidget.widget(index)
widget.deleteLater()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
As you can see, it is not necessary to use the attribute Qt::WA_DeleteOnClose, but if you use it, it would be enough to close the widget.
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tabWidget = QtWidgets.QTabWidget(tabsClosable=True)
self.tabWidget.tabCloseRequested.connect(self.onTabCloseRequested)
self.setCentralWidget(self.tabWidget)
for i in range(10):
widget = QtWidgets.QWidget()
widget.setAttribute(QtCore.Qt.WA_DeleteOnClose)
widget.destroyed.connect(
lambda obj: print(
"deleted {}, count: {}".format(obj, self.tabWidget.count())
)
)
self.tabWidget.addTab(widget, "Tab %s" % (i))
@QtCore.pyqtSlot(int)
def onTabCloseRequested(self, index):
widget = self.tabWidget.widget(index)
widget.close()
It is not necessary to use removeTab()
since this does not destroy the widget, that method is thought so that when you want to place the widget removed to another widget.