首页 > 解决方案 > 动态创建的选项卡 - 关闭选项卡时销毁对象

问题描述

我正在动态创建多个选项卡,我想知道当我关闭选项卡时,它是否真的破坏了对象?

我已将动态创建的选项卡的属性设置为 QtCore.Qt.WA_DeleteOnClose

我假设设置属性不会做任何事情,因为 closeEvent 没有被调用。

    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:')

如何确保对象被销毁?

标签: pythonmemory-leakspyqtpyqt5qtabwidget

解决方案


我的回答旨在解释其他答案未指出的细节,以便您了解它如何处理内存 Qt。

如果您想知道 QObject 是否被消除,那么您必须使用该destroyed信号。

如果你想删除一个 QObject,你必须使用deleteLater()方法。

在消除添加到 QTabWidget 的小部件的情况下,这将通知 QTabBar 它将被删除,因此访问非保留内存没有问题。

考虑到上述情况,一个可能的解决方案是:

def close_handler(self, index):
    widget = self.tabWidget.widget(index)
    widget.deleteLater()

您可以通过以下示例进行检查:

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_())

如您所见,没有必要使用属性 Qt::WA_DeleteOnClose,但如果使用它,关闭小部件就足够了。

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()

由于这不会破坏小部件,因此没有必要使用removeTab()该方法,因此当您要将小部件移除到另一个小部件时,可以考虑使用该方法。


推荐阅读