【问题标题】:PyQt connect() call affecting multiple widgetsPyQt connect() 调用影响多个小部件
【发布时间】:2015-03-13 04:56:06
【问题描述】:

为程序制作 PushButton 小部件。目的是创建每个 PushButton,将其连接到比较两个字符串值的函数 ap.parse_answer(),然后将 PushButton 添加到 QGridLayout 的适当单元格:

answers = ["this", "that", "the other", "one more"]
correct_answer = "this"

for grid_pos in [(i,j) for i in range(0,2) for j in range(0,2)]:
        answer_disp = AnswerDisplay()
        current_answer = answers.pop()
        answer_disp.setText(current_answer)
        answer_disp.clicked.connect(
            lambda: self.ap.parse_answer(current_answer, answer))
        answer_grid.addWidget(answer_disp, *grid_pos)

这是 AnswerDisplay 类:

class AnswerDisplay(QtGui.QPushButton):
    def __init__(self):
        super(AnswerDisplay, self).__init__()
        answer_font = QtGui.QFont()
        answer_font.setWeight(24)
        answer_font.setPixelSize(20)
        self.setFont(answer_font)

不幸的是,每个按钮都连接了相同的功能。生成的最后一个函数最终出现在所有按钮上,因此似乎连接正在重新应用于先前创建的按钮。但是我该如何解决这个问题?我的方法不可能完全无效,因为 setText() 函数正确地为每个按钮设置了文本,而不会覆盖之前的分配。

我试图解决制作单个 AnswerDisplay 然后使用 deepcopy() 复制它的问题:

for grid_pos in [(i,j) for i in range(0,2) for j in range(0,2)]:
    disp = AnswerDisplay()
    answer_disp = deepcopy(disp)
    super(AnswerDisplay, answer_disp).__init__()
    ...

但它产生了同样不受欢迎的结果。

我进行了一些搜索,但我发现的只是人们试图获得我尝试获得的结果的问题。任何帮助将不胜感激。

【问题讨论】:

标签: python python-3.x pyqt


【解决方案1】:

您的问题是您没有捕获 lambda 函数中的值。由于 Python 的作用域规则的工作方式,您每次都使用相同的值(最后一个)。

将 lambda 行改为 capture 你想要的变量:

answer_disp.clicked.connect(
    lambda ca=current_answer, a=answer: self.ap.parse_answer(ca, a))

还有其他相关的问题/答案可能会给你更多的解释(比如here

【讨论】:

  • 非常有趣,我认为这也解释了我在使用 lambda 表达式时遇到的一些其他问题。在这种情况下,我不确定。现在每个按钮都将False 作为current_answer 的值传递给parse_answer()。按钮名称仍在正确设置,因此将一个已知包含字符串的变量输入到 lambda 中,但如果我将 print() 语句添加到 parse_answers() 以显示传递给它的参数,则 lambda 似乎正在生成作业ca=False
  • @Jefe:我不确定您的确切问题是什么,但在您发布的示例中,变量:answer 没有被分配到任何地方,所以这可能是其中的一部分。也许您的实际代码不是您在此处发布的代码?
  • 我确信这与我对 lambda 函数缺乏理解有关,但这是一个奇怪的问题。在 lambda 表达式中首先进行的哪个赋值被设置为 False。所以,lambda ca=current_answer, a=answer: self.ap.parse_answer(ca, a) 传递 (False, "answer string") 和 lambda a=answer, ca=current_answer: self.ap.parse_answer(ca, a) 传递 ("current answer string", False) 到 parse_answer()。
  • @Jefe 如果您仍然遇到问题,发布一个简单的工作示例来演示奇怪的行为可能会帮助其他人调试问题。
猜你喜欢
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-05
  • 2018-08-14
  • 1970-01-01
相关资源
最近更新 更多