QWidget
を含むクラスクラスがありQLabel
ます。クラスはQCheckbox
'es を生成しQVBox
ます。各チェックボックスを、最後のチェックボックスのタイトルを表示する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
いくつかの「ハック」ソリューションを見つけました。
解決策 1 : callBack 関数を作成するとうまくいきます。
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] ) )
ただし、ラムダ式を1行で使用したいと思います。特に、それがどのように機能するかを理解したいと思います。リンクをたどると、問題はラムダスコープに関するものであることがわかりました。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
変数は int と見なされるようですか? そこで何が起こるの?