2012-02-04 52 views
5

在PySide/PyQt中區分許多相同類型的信號源有沒有簡單或優雅的方法?區分PySide中的信號源

我正在學習PySide。我寫了一個簡單的應用程序,它將來自兩個不同的QLineEdit()對象的兩個數字相乘。結果顯示在第三個QLineEdit中。

乘數和被乘數QLineEdit.textChanged()信號連接到一個方法(TxtChanged)。在這種方法中,我必須區分信號源。一些試驗後,我想出了一些解決方法基於佔位符文本(以下4行「有另一種方式?」在我的代碼註釋)

代碼:

import sys 
from PySide import QtGui, QtCore 

class myGUI(QtGui.QWidget): 

    def __init__(self, *args, **kwargs): 
     QtGui.QWidget.__init__(self, *args, **kwargs) 

     self.multiplier = 0 
     self.multiplicand = 0 

     self.myGUIInit() 

    def myGUIInit(self): 
     # input forms 
     a1_label = QtGui.QLabel("a1") 
     a1_edit = QtGui.QLineEdit() 
     a1_edit.setPlaceholderText("a1") 

     a2_label = QtGui.QLabel("a2") 
     a2_edit = QtGui.QLineEdit() 
     a2_edit.setPlaceholderText("a2") 

     # output form 
     a1a2_label = QtGui.QLabel("a1*a2") 
     self.a1a2_edit = QtGui.QLineEdit() 
     self.a1a2_edit.setReadOnly(True) 


     # forms events 
     a1_edit.textChanged.connect(self.TxtChanged) 
     a2_edit.textChanged.connect(self.TxtChanged) 

     # grid 
     grid = QtGui.QGridLayout() 
     grid.setSpacing(10) 

     grid.addWidget(a1_label,1,0) 
     grid.addWidget(a1_edit,1,1) 

     grid.addWidget(a2_label,2,0) 
     grid.addWidget(a2_edit,2,1) 

     grid.addWidget(a1a2_label,3,0) 
     grid.addWidget(self.a1a2_edit,3,1) 

     self.setLayout(grid) 
     self.setGeometry(100,100,200,200) 
     self.setWindowTitle("a*b") 
     self.show() 

    def TxtChanged(self,text): 
     sender = self.sender() 
     sender_text = sender.text() 
     if sender_text == '': sender_text = '0' 

     # is there another way? 
     if sender.placeholderText() == 'a1': 
      self.multiplicand = sender_text 
     else: 
      self.multiplier = sender_text 

     product = int(self.multiplier) * int(self.multiplicand) 

     print(self.multiplier,self.multiplicand,product) 

     self.a1a2_edit.setText(str(product)) 


def main(): 
    app = QtGui.QApplication(sys.argv) 
    mainWindow = myGUI() 
    sys.exit(app.exec_()) 

main() 

最好的問候, ostrzysz

+0

謝謝大家的答案。最好的祝福! – ostrzysz 2012-02-05 08:54:44

回答

3

在您的代碼中,最讓我誤解的一件事是您正在使用placeholderText來區分。 QObject s有另一個屬性objectName更適合您的任務。而且,您不需要使用sender.text()來獲取QLineEdit的文本。 textChanged已經發送了它,所以你可以在你的text參數中找到它。

此外,使用字典而不是兩個單獨的變量(multipliermultiplicand)將進一步簡化您的代碼。

這裏是改變的代碼:

class myGUI(QtGui.QWidget): 

    def __init__(self, *args, **kwargs): 
     QtGui.QWidget.__init__(self, *args, **kwargs) 

     self.data = {"multiplier": 0, 
        "multiplicand": 0} 

     self.myGUIInit() 

    def myGUIInit(self): 
     a1_label = QtGui.QLabel("a1") 
     a1_edit = QtGui.QLineEdit() 
     a1_edit.setObjectName("multiplicand") 

     a2_label = QtGui.QLabel("a2") 
     a2_edit = QtGui.QLineEdit() 
     a2_edit.setObjectName("multiplier") 

     # skipped the rest because same 

    def TxtChanged(self, text): 
     sender = self.sender() 

     # casting to int while assigning seems logical. 
     self.data[sender.objectName()] = int(text) 

     product = self.data["multiplier"] * self.data["multiplicand"] 

     print(self.data["multiplier"], self.data["multiplicand"], product) 

     self.a1a2_edit.setText(str(product)) 
+0

關於'setObjectName'的好處,但我個人更喜歡'functools。部分'方法就像在@jsbueno的答案,因爲它是明確的。 'QObject.sender()'有許多缺點,例如在多線程環境中。 – reclosedev 2012-02-05 07:05:30

+0

非常感謝您,那正是我一直在尋找的!最好的祝福。 – ostrzysz 2012-02-05 08:52:38

6

您可以使用functools.partial函數 - 因此將您的信號直接連接到您的方法/函數,而是連接到一個python對象,該對象將自動調用您的函數並傳遞一些額外的數據:

from functools import partial 
... 
     .... 
     a1_edit.textChanged.connect(partial(self.TxtChanged, a1_edit)) 
     a2_edit.textChanged.connect(partial(self.TxtChanged, a2_edit)) 
     ... 

    def TxtChanged(self,sender, text): 
     # and here you have the "sender" parameter as it was filled in the call to "partial" 
     ... 

分音是STDLIB的一部分,並且是非常可讀的,但人們總是可以使用的λ,而不是局部的相同的效果 -

a1_edit.textChanged.connect(lambda text: self.TxtChanged(a1_edit, text)) 

以這種方式通過λ表達式產生該對象將是一個暫時的函數將使用當前局部變量(點擊按鈕時)的「self」和「a1_edit」的值,並且Pyside的回調將提供名爲「text」的變量。

2

雖然@jsbueno@Avaris回答您的問題直接有關的信號源,我不會對這個來源在您的具體情況中繼。您可以實例成員a1_edita2_edit

... 
self.a1_edit = QtGui.QLineEdit() 
... 
self.a2_edit = QtGui.QLineEdit() 
... 

這將簡化您的TxtChanged功能:

def TxtChanged(self,text): 
    try: 
     multiplier = int(self.a1_edit.text()) 
     multiplicand = int(self.a2_edit.text()) 
    except ValueError: 
     self.a1a2_edit.setText('Enter two numbers') 
     return 
    product = multiplier * multiplicand 
    print(multiplier, multiplicand, product) 
    self.a1a2_edit.setText(str(product)) 

此外,而不是處理ValueError例外,您可以使用QIntValidator輸入控件:

self.int_validator = QtGui.QIntValidator() 
self.a1_edit.setValidator(self.int_validator) 
self.a2_edit.setValidator(self.int_validator)