添加qmenubar后析构函数未被调用

2 投票
1 回答
791 浏览
提问于 2025-04-17 01:58

我有以下文件(主窗口/用户界面):

文件

用户界面:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created: Sat Apr 23 15:53:12 2011
#     by: PyQt4 UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

class Ui_MainWindow(object):
    ### Presetting Model ###
    model = QtGui.QFileSystemModel()
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1000, 600)    
        self.centralWidget = QtGui.QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")
        self.horizontalLayout_2 = QtGui.QHBoxLayout(self.centralWidget)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.treeView = QtGui.QTreeView(self.centralWidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(2)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.treeView.sizePolicy().hasHeightForWidth())
        self.treeView.setSizePolicy(sizePolicy)
        self.treeView.setHeaderHidden(True)
        self.treeView.setObjectName("treeView")
        self.horizontalLayout.addWidget(self.treeView)
        self.plainTextEdit = QtGui.QPlainTextEdit(self.centralWidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(4)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.plainTextEdit.sizePolicy().hasHeightForWidth())
        self.plainTextEdit.setSizePolicy(sizePolicy)
        self.plainTextEdit.setObjectName("plainTextEdit")
        self.horizontalLayout.addWidget(self.plainTextEdit)
        self.horizontalLayout_2.addLayout(self.horizontalLayout)
        MainWindow.setCentralWidget(self.centralWidget)
        ### MENU ###
        self.menuBar = QtGui.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 600, 27))
        self.menuBar.setObjectName("menuBar")
        MainWindow.setMenuBar(self.menuBar)

        ### Setting up tree view model ###
        self.treeView.setModel(self.model)
        self.treeView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
#       self.treeView.setRootIndex(self.model.setRootPath(Xmldocument.directorypath))

        ### Hiding additional info in treeview ###
        hHeader = self.treeView.header()
        hHeader.hideSection(1)
        hHeader.hideSection(2)
        hHeader.hideSection(3)

        MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "VeloCondDB Browser", None, QtGui.QApplication.UnicodeUTF8))
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

##############################################################

    def __del__(self):
        print "DESTRUCTOR"  

主窗口:

import sys
import os

from browserclass_UI import Ui_MainWindow
from PyQt4 import QtCore, QtGui

class Browser(QtGui.QMainWindow):

#############################################################################################

    def __init__(self, parent=None):
        """Constructor for the main window."""

        QtGui.QWidget.__init__(self, parent)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        menuitems = ["Open", "Close"]
        menu = self.ui.menuBar.addMenu('File')
        for item in menuitems:
            entry = menu.addAction(item)
            self.connect(entry, QtCore.SIGNAL('triggered()'), lambda item=item: self.doStuff(item)) 

#############################################################################################

    def doStuff(self, item):
        print item

#############################################################################################

if __name__ == "__main__":
    browser = QtGui.QApplication(sys.argv)
    myapp = Browser()
    myapp.show()
    sys.exit(browser.exec_())

当以下代码行:

menuitems...

self.connect...

没有被注释掉时,用户界面的析构函数就不会被调用。如果把它们注释掉,一切就正常了。有什么想法吗?

1 个回答

2

你不能指望所有对象的 __del__ 方法都会被调用,特别是在你的程序结束的时候(可以参考这个答案

根据PyQt的文档

不过,如果一个槽是一个lambda函数或者部分函数,那么它的引用计数会自动增加,以防止它被立即垃圾回收。

当你把信号连接到lambda函数时,可能会创建一些对你的 Browser 对象的循环引用,这就是它无法被销毁的原因。因为 uiBrowser 引用,所以它也不会被销毁。

所以,当这些槽是lambda函数时,你必须手动断开连接。或者使用其他方法来绑定额外的参数到槽(例如,使用 QSignalMapper,或者信号 QMenu.triggered,它的参数是 QAction):

def __init__(self, parent):
    ...
    for item in menuitems:
        entry = menu.addAction(item)
    menu.triggered.connect(self.doStuff)

def doStuff(self, entry):
    print entry.text()

撰写回答