出于某种原因,运行此代码只会将颜色切换为蓝色,当它应该单独切换每种颜色时。
这段代码是我http://eli.thegreenplace.net/2011/04/25/passing-extra-arguments-to-pyqt-slot示例代码的版本,这是我刚刚开始学习的PyQt教程。
import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
QFrame, QApplication)
from PyQt5.QtGui import QColor
class Example(QWidget):
red = False
blue = False
green = False
buttons = []
def __init__(self):
super().__init__()
self.init_UI()
def init_UI(self):
self.col = QColor(0, 0, 0)
for x in range(0, 3):
self.buttons.append(QPushButton('Red' if x == 0 else ('Green' if x == 1 else 'Blue'), self))
self.buttons[x].setCheckable(True)
self.buttons[x].move(10, 10 + 50 * x)
self.buttons[x].clicked[bool].connect(lambda: self.set_color(x))
self.square = QFrame(self)
self.square.setGeometry(150, 20, 100, 100)
self.square.setStyleSheet("QWidget { background-color: %s }" %
self.col.name())
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('Toggle button')
self.show()
def set_color(self, button):
if button == 0:
if self.red == False:
self.red = True
self.col.setRed(255)
else:
self.red = False
self.col.setRed(0)
elif button == 1:
if self.green == False:
self.green = True
self.col.setGreen(255)
else:
self.green = False
self.col.setGreen(0)
else:
if self.blue == False:
self.blue = True
self.col.setBlue(255)
else:
self.blue = False
self.col.setBlue(0)
self.square.setStyleSheet("QFrame { background-color: %s }" %
self.col.name())
print(self.col.name())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
答案 0 :(得分:2)
connect(lambda: self.set_color(x))
不起作用的原因是x
仅在调用lambda时才会被评估,即在发出信号之后,在循环完成后将会更晚。因此set_color()
会在信号发出时收到x
的值。在你的代码中,这将是x
在循环中的最后一个值,即2.
虽然@ Hi的回答是有效的,但我发现Achayan的解决方案(在评论中提到)更明确,并且工作得很好(与某些评论相反 - 我用代码验证了它):
for x in range(0, 3):
...
self.buttons[x].clicked[bool].connect(partial(self.set_color, x))
这可行的原因是x
是函数调用的参数(函数为functools.partial
),因此x
立即计算 。当partial(f, a)
是一个arg的函数时,f
返回的函数是一个函数g()
,它不带参数并调用f(a)
。