Python PyQt-从字典创建按钮
我有一本字典。Python PyQt-从字典创建按钮,python,pyqt,Python,Pyqt,我有一本字典。 我需要创建带有键名的按钮,并根据值单击插槽: dic = {'a':'111', 'b':'222', 'c':'333'} for key in dic: btn = QPushButton(key, self) btn.clicked.connect(lambda: doit(dic[key])) vbox.addWidget(btn) 我所有的按钮都有正确的名字。最后创建的按钮的行为正确。 但是所有其他按钮的点击插槽也连接到最后创建的按钮do('
我需要创建带有键名的按钮,并根据值单击
插槽:
dic = {'a':'111', 'b':'222', 'c':'333'}
for key in dic:
btn = QPushButton(key, self)
btn.clicked.connect(lambda: doit(dic[key]))
vbox.addWidget(btn)
我所有的按钮都有正确的名字。最后创建的按钮的行为正确。但是所有其他按钮的
点击
插槽也连接到最后创建的按钮do('333')
如何使所有按钮的行为都有所不同?我认为问题在于,当您调用lambda:doit(dic[key])时,它确实会这样做,并查找dic[key],此时key被设置为上一个迭代通过的项 试试这个:
dic = {'a':'111', 'b':'222', 'c':'333'}
def create_connect(x):
return lambda: doit(x)
for key in dic:
btn = QPushButton(key, self)
btn.clicked.connect(create_connect(dic[key]))
vbox.addWidget(btn)
我认为问题在于,当您调用lambda:doit(dic[key])时,它实际上就是这样做的,并查找dic[key],此时key被设置为迭代通过的最后一项是什么 试试这个:
dic = {'a':'111', 'b':'222', 'c':'333'}
def create_connect(x):
return lambda: doit(x)
for key in dic:
btn = QPushButton(key, self)
btn.clicked.connect(create_connect(dic[key]))
vbox.addWidget(btn)
匿名函数
lambda:doit(dic[key])
在调用该函数之前不会计算key
。此时,循环的已完成,循环的变量key
引用了dic
中的最后一个键
调用匿名函数时(当您按下按钮时),key
将在全局命名空间中查找,并返回当前值key
为了避免这个陷阱,可以在lambda
表达式中使用默认参数:
for key in dic:
btn = QPushButton(key, self)
btn.clicked.connect(lambda key=key: doit(dic[key]))
vbox.addWidget(btn)
默认参数在定义时计算,而不是在调用lambda时计算。通过执行此操作,key
将在匿名函数的本地名称空间中查找,而不是在全局名称空间中查找,并且由于key的本地名称空间值被设置为默认值,这对于for循环的每次传递都是不同的,因此您可以获得key
的正确值
这也在本文中进行了解释。匿名函数lambda:doit(dic[key])
在调用该函数之前不会计算key
。此时,循环的已完成,循环的变量key
引用了dic
中的最后一个键
调用匿名函数时(当您按下按钮时),key
将在全局命名空间中查找,并返回当前值key
为了避免这个陷阱,可以在lambda
表达式中使用默认参数:
for key in dic:
btn = QPushButton(key, self)
btn.clicked.connect(lambda key=key: doit(dic[key]))
vbox.addWidget(btn)
默认参数在定义时计算,而不是在调用lambda时计算。通过执行此操作,key
将在匿名函数的本地名称空间中查找,而不是在全局名称空间中查找,并且由于key的本地名称空间值被设置为默认值,这对于for循环的每次传递都是不同的,因此您可以获得key
的正确值
这也在本文中进行了解释。您的迭代需要字典dic的键和值。
您可以使用dict.iteritems()方法。
如果lambda变得混乱,那么最好使用partial
试试这个:
from PyQt4.QtGui import QApplication, QWidget, QVBoxLayout, QPushButton
from functools import partial
class MainWidget(QWidget):
def __init__(self):
super(MainWidget, self).__init__()
dic = {'a':'111', 'b':'222', 'c':'333'}
vbox = QVBoxLayout(self)
for key,val in dic.iteritems():
btn = QPushButton(key, self)
btn.clicked.connect(partial(self.doit, val))
vbox.addWidget(btn)
def doit(self, text):
print "%s" % text
if __name__ == "__main__":
app = QApplication([])
w = MainWidget()
w.show()
app.exec_()
迭代需要字典dic的键和值。
您可以使用dict.iteritems()方法。
如果lambda变得混乱,那么最好使用partial
试试这个:
from PyQt4.QtGui import QApplication, QWidget, QVBoxLayout, QPushButton
from functools import partial
class MainWidget(QWidget):
def __init__(self):
super(MainWidget, self).__init__()
dic = {'a':'111', 'b':'222', 'c':'333'}
vbox = QVBoxLayout(self)
for key,val in dic.iteritems():
btn = QPushButton(key, self)
btn.clicked.connect(partial(self.doit, val))
vbox.addWidget(btn)
def doit(self, text):
print "%s" % text
if __name__ == "__main__":
app = QApplication([])
w = MainWidget()
w.show()
app.exec_()
但是怎么做呢?这与
的有何联系?这个把戏有名字吗?如果没有for,就不需要这个哑函数。我认为lambda:
解决了所有这些问题。但是情况变得更糟了,但是怎么会呢?这与
的有何联系?这个把戏有名字吗?如果没有for,就不需要这个哑函数。我认为lambda:
解决了所有这些问题。但情况变得更糟了。谢谢你们的回答和链接,我开始明白了。Bwmat的方法正在工作,但是lambda key=key:
和lambda key=key:self.label.setText(key)
返回TypeError:QLabel.setText(str):参数1有意外的类型“bool”
。如果没有key=key
,它的工作原理与问题中的一样。我不明白bool
从哪里来。@Qiao:usinglambda key=key:
在没有参数传递给lambda函数的情况下有效。这允许键
采用默认值。如果参数被传递给lambda函数,那么key
将被指定该值。看起来有一个布尔值被传递到lambda函数,并被分配到键
。感谢您的回答和链接,我开始获取它。Bwmat的方法正在工作,但是lambda key=key:
和lambda key=key:self.label.setText(key)
返回TypeError:QLabel.setText(str):参数1有意外的类型“bool”
。如果没有key=key
,它的工作原理与问题中的一样。我不明白bool
从哪里来。@Qiao:usinglambda key=key:
在没有参数传递给lambda函数的情况下有效。这允许键
采用默认值。如果参数被传递给lambda函数,那么key
将被指定该值。看起来有一个布尔值被传递到lambda函数,并被分配到键
。