我有一个类QWidget,其中包含一个QLabel。该类在QVBox中生成QCheckbox。我试图将每个复选框连接到方法nameCheckBox,该方法将更新QLabel以显示最后一个选中框的标题。然而,当复选框有效地被选中/取消选中时,它始终被检测为未选中。此外,返回的名称始终是最后创建的复选框。我不明白我的错误在哪里。以下是我的代码:
import sys
from PyQt4 import QtCore
from PyQt4.QtGui import *
from MenusAndToolbars import MenuWindow
class checkBoxWidget(QWidget):
"""
This widget has a QVBox which contains a QLabel and QCheckboxes.
Qcheckbox number is connected to the label.
"""
def __init__(self):
QWidget.__init__(self)
self.__setUI()
def __setUI(self):
vbox = QVBoxLayout(self)
label = QLabel('Last clicked button: ' + "None", self)
vbox.addWidget(label)
listCB = []
for i in range(10):
listCB.append( QCheckBox('CheckBox Nb. ' + str(i+1) ) )
listCB[i].stateChanged.connect(lambda: self.nameCheckBox(label, listCB[i]) )
vbox.addWidget( listCB[i] )
def nameCheckBox(self, label, checkBox):
if checkBox.isChecked():
print "Checked: " + checkBox.text()
label.setText('Last clicked button: ' + checkBox.text())
else:
print "Unchecked: " + checkBox.text()
def main():
app = QApplication(sys.argv)
window = QMainWindow()
window.setCentralWidget( checkBoxWidget() )
window.show()
#window = WidgetWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
编辑1
我找到了几个“hack”解决方案。
解决方案1:创建一个回调函数即可解决问题:
def callBack(self, list, index, label):
return lambda: self.nameCheckBox(label, list[index])
我使用以下方式连接QCheckbox().stateChanged
信号:
listCB[i].stateChanged.connect( self.callBack(listCB, i, label) )
解决方案2:使用 partial
模块:
首先,我们需要导入该模块:
from functools import partial
那么信号连接是这样完成的:
listCB[i].stateChanged.connect( partial( self.nameCheckBox, label, listCB[i] ) )
然而,我想在一行中使用Lambda表达式。 特别是我想了解它是如何工作的。 通过以下链接,我理解了问题与Lambda范围有关。 正如Oleh Prypin所建议的那样,我写了:
listCB[i].stateChanged.connect(lambda i=i: self.nameCheckBox(label, listCB[i]) )
这里的变量i
是一个新的变量。然而,我的原始问题仍然存在。出于好奇,我尝试了以下操作:
listCB[i].stateChanged.connect( lambda label=label, listCB=listCB, i=i: self.nameCheckBox(label, listCB[i] ) )
但我遇到了以下错误:
Traceback (most recent call last):
Checked: CheckBox Nb. 2
File "Widgets.py", line 48, in <lambda>
listCB[i].stateChanged.connect( lambda label=label, listCB=listCB, i=i: self.nameCheckBox(label, listCB[i] ) )
File "Widgets.py", line 59, in nameCheckBox
label.setText('Last clicked button: ' + checkBox.text())
AttributeError: 'int' object has no attribute 'setText'
看起来正确的按钮在勾选/取消时被识别了。然而,新的label
变量似乎被视为一个整数?这里会发生什么?
listCB
的范围也有问题? - kalignesender()
方法,这证明它非常有用。我想我需要系统地检查文档中信号返回的值? - kalignelambda checked, i=i: self.nameCheckBox(label, listCB[i])
)对我来说完美运作了,谢谢! - Nicholas Barrow