2012-02-04 4 views
5

PySide/PyQtの多くの同じタイプの信号ソースを区別するための些細なことやエレガントな方法はありますか?PySideの信号ソースを区別する

私はPySideを学んでいます。私は2つの異なるQLineEdit()オブジェクトから2つの数値を乗算する簡単なアプリケーションを書いています。結果は3番目のQLineEditに表示されます。

マルチプライヤと被乗数QLineEdit.textChanged()信号は、1つのメソッド(TxtChanged)に接続されています。この方法では、信号源を区別する必要があります。

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

答えて

3

あなたのコードで私が最も嫌な点は、placeholderTextを使って区別することです。 QObjectには、objectNameと呼ばれる別のプロパティがあり、これはあなたのタスクに適しています。また、QLineEditのテキストを取得するためにsender.text()を使用する必要はありません。 textChangedは既にそれを送信していますので、textパラメータに入力してください。

また、2つの別々の変数(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()'には多くの欠点があります。 mutlithreaded環境で実行します。 – reclosedev

+0

ありがとうございました、それはまさに私が探していたものです!宜しくお願いします。 – ostrzysz

6

:いくつかの試行後、私はプレースホルダーテキスト(「?別の方法がある」4行以下の私のコード内のコメント)

コードに基づいて、いくつかの回避策を考え出しました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"の値を使用し、 "text"という名前の変数はPysideのコールバックから供給されます。

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) 
関連する問題