我已经准备好很多关于如何在 python 和 pyqt 中将多个信号连接到同一个事件处理程序的帖子。例如,将多个按钮或组合框连接到同一个功能。
许多示例展示了如何使用 QSignalMapper 执行此操作,但是当信号带有参数时它不适用,例如 combobox.currentIndexChanged
许多人建议它可以用 lambda 制作。我同意,这是一个干净而漂亮的解决方案,但没有人提到 lambda 创建了一个包含引用的闭包——因此不能删除被引用的对象。你好内存泄漏!
证明:
from PyQt4 import QtGui, QtCore
class Widget(QtGui.QWidget):
def __init__(self):
super(Widget, self).__init__()
# create and set the layout
lay_main = QtGui.QHBoxLayout()
self.setLayout(lay_main)
# create two comboboxes and connect them to a single handler with lambda
combobox = QtGui.QComboBox()
combobox.addItems('Nol Adyn Dwa Tri'.split())
combobox.currentIndexChanged.connect(lambda ind: self.on_selected('1', ind))
lay_main.addWidget(combobox)
combobox = QtGui.QComboBox()
combobox.addItems('Nol Adyn Dwa Tri'.split())
combobox.currentIndexChanged.connect(lambda ind: self.on_selected('2', ind))
lay_main.addWidget(combobox)
# let the handler show which combobox was selected with which value
def on_selected(self, cb, index):
print '! combobox ', cb, ' index ', index
def __del__(self):
print 'deleted'
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
wdg = Widget()
wdg.show()
wdg = None
sys.exit(app.exec_())
尽管我们清除了引用,但小部件并未被删除。删除与 lambda 的连接 - 它被正确删除。
所以,问题是:在不泄漏内存的情况下,将多个带参数的信号连接到单个处理程序的正确方法是什么?