2016-10-22 52 views
0

由於某種原因,運行此代碼時,只會切換顏色爲藍色,當它應該單獨切換每種顏色時。該代碼如何才能切換藍色? (Python,PyQt)

此代碼是我在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_()) 

回答

1

之所以connect(lambda: self.set_color(x))不起作用是x將只有當拉姆達被調用來評價,即當信號被髮射,這將在很久以後,循環完成後。因此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評估立即。當f是一個arg的函數時,由partial(f, a)返回的函數是一個函數g(),它不接受任何參數並將調用f(a)

+0

只是要清楚:我的意見不是關於「partial」,而是關於現在已被刪除的答案中錯誤使用lambda的。我給出了正確的用法,這是:connect(lambda checked,x = x:self.set_color(x))'。這實際上比'partial'更明確,因爲它包含'clicked'信號發送參數的'checked'參數。但顯然,任何一種解決方案都可以。 – ekhumoro

相關問題