2017-02-25 10 views
0

変数のセットから多数の計算を行うクラスのUIを作成する必要があります。コードはおおよそ次のようになります。関数からの名前によるアクセスインスタンス変数

class MainWindow: 
    def __init__(self): 
     pulse = Pulse() 

     self.var1_lineEdit.textEdited.connect(self.set_attribute(pulse, "var1", new_value)) 
     self.var2_lineEdit.textEdited.connect(self.set_attribute(pulse, "var2", new_value)) 
     self.var3_lineEdit.textEdited.connect(self.set_attribute(pulse, "var3", new_value)) 
     .... 

    def set_attribute(pulse, var_name, value): 
     # get value from line edit 
     # update value in pulse 
     # update other calculations 

class Pulse: 
    def __init__(self): 
     var1 = 1 
     var2 = 2 
     var3 = 3 
     .... 

ここで問題となるのは、set_attributeをコーディングする方法です。名前を関数の引数として渡すことによって別のクラスの個々の変数にアクセスする方法はありますか?私は各変数に新しい関数を定義する必要がないようにしたいと思います。

これを行う簡単な方法はありますか?私はOOPとUIをコーディングする適切な方法に慣れていません。あなたが提案してきた

+1

組み込みの['setattr'](https://docs.python.org/3/library/functions.html#setattr)機能がほしいと思うようです。 – jonrsharpe

+0

私が@ waterboy5281を正しく理解していれば、それはそれより複雑です。私は複数の信号を1つのスロットに接続しようとしていますが、信号出力に応じて異なる結果が得られます – MisterTea

答えて

1

EDIT

シグナル/スロット接続がトラブルにあなたを取得します。シグナルはconnect関数を使用してスロットに接続されます。これは関数呼び出し自体ではなく、引数としてpython呼び出し可能を受け入れます。それはどういう意味ですか

widget.textChanged.connect(self.set_attribute) # right syntax 
widget.textChanged.connect(self.set_attribute()) # wrong syntax 

それでは、どうすればいいですか?set_attributeどうすればいいですか? ekhumoroは私の方法の誤りを私に知らせた:QSignalMapperの使用。それは時代遅れのテクニックです。希望の効果を得るには、lambda機能(またはpartials)を使用するのがベストです。

私はこのデモの目的のためにlambdas

の使用のための私のデモを更新し、私は2つのQLineEditウィジェットとQPushButtonでシンプルなQMainWindowを作成しました。別のファイルで

# file ui_main.py 
from PyQt5 import QtCore, QtGui, QtWidgets 

class Ui_MainWindow(object): 
    def setupUi(self, MainWindow): 
     MainWindow.setObjectName("MainWindow") 
     MainWindow.resize(359, 249) 
     self.centralwidget = QtWidgets.QWidget(MainWindow) 
     self.centralwidget.setObjectName("centralwidget") 
     self.formLayoutWidget = QtWidgets.QWidget(self.centralwidget) 
     self.formLayoutWidget.setGeometry(QtCore.QRect(0, 0, 351, 51)) 
     self.formLayoutWidget.setObjectName("formLayoutWidget") 
     self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget) 
     self.formLayout.setObjectName("formLayout") 
     self.configParam1Label = QtWidgets.QLabel(self.formLayoutWidget) 
     self.configParam1Label.setObjectName("configParam1Label") 
     self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.configParam1Label) 
     self.configEntry = QtWidgets.QLineEdit(self.formLayoutWidget) 
     self.configEntry.setObjectName("configEntry") 
     self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.configEntry) 
     self.configParam2Label = QtWidgets.QLabel(self.formLayoutWidget) 
     self.configParam2Label.setObjectName("configParam2Label") 
     self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.configParam2Label) 
     self.configEntry2 = QtWidgets.QLineEdit(self.formLayoutWidget) 
     self.configEntry2.setObjectName("configEntry2") 
     self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.configEntry2) 
     self.pulseButton = QtWidgets.QPushButton(self.centralwidget) 
     self.pulseButton.setGeometry(QtCore.QRect(130, 140, 75, 23)) 
     self.pulseButton.setObjectName("pulseButton") 
     MainWindow.setCentralWidget(self.centralwidget) 

     self.retranslateUi(MainWindow) 
     QtCore.QMetaObject.connectSlotsByName(MainWindow) 

    def retranslateUi(self, MainWindow): 
     _translate = QtCore.QCoreApplication.translate 
     MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) 
     self.configParam1Label.setText(_translate("MainWindow", "Config Param 1")) 
     self.configParam2Label.setText(_translate("MainWindow", "Config Param 2")) 
     self.pulseButton.setText(_translate("MainWindow", "GetPulse")) 

、一部の輸入後、そのUIを設定し、それをPulseを与え、MainWindowを定義し、Pulseに今、二つの属性

# file main.py 
from PyQt5.QtCore import (QSignalMapper, pyqtSlot) 
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMessageBox) 

from ui_main import Ui_MainWindow 

class Pulse: 
    def __init__(self): 
     self.param_one = None 
     self.param_two = None 

が含まれています--a単純なクラスを定義します。

class MainWindow(QMainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 

     self.pulse = Pulse() 

     self.ui = Ui_MainWindow() 
     self.ui.setupUi(self) 

     self.widget_one = self.ui.configEntry 
     self.widget_two = self.ui.configEntry2 
     self.pulse_button = self.ui.pulseButton 

     self.widget_one.textChanged.connect(lambda: self.widget_handler('param_one', self.widget_one.text())) 
     self.widget_one.textChanged.connect(lambda: self.widget_handler('param_two', self.widget_two.text())) 

    def widget_handler(self, attr, value): 
     setattr(self.pulse,attr,value) 

    def handler(self, idx): 
     widget, attr = self.attribute_widget_list[idx] 
     widget_value = widget.text() 
     setattr(self.pulse,attr,widget_value) 

setattrは、例えば、self.pulse.param_one = widget_valueに相当します。

@pyqtSlot() 
    def on_pulseButton_clicked(self): 
     message = QMessageBox() 
     message.setText("{} - {}".format(self.pulse.param_one, self.pulse.param_two)) 
     message.exec() 

ここで私はあなたがおよそhere

を読むことができます異なるシグナル/スロット接続方式を、使用しています:のはQPushButtonPulseの状態を調べるためにすることを使用してみましょう、それが動作することを証明する

スクリプトを実行する方法は次のとおりです。

if __name__ == '__main__': 
    import sys 

    app = QApplication(sys.argv) 
    window = MainWindow() 
    window.show() 
    sys.exit(app.exec_()) 

希望に役立ちます。

+0

接続機能のリマインダーに感謝します。私は盲目的に各編集行の変更のすべての属性を更新する関数を書いていましたが、それは仕事をしますが、それはちょっとです。あなたのソリューションは非常に興味深いようですが、私はあなたが私のUIの最初のバージョンを実行すると、それを試してみましょう。 – MisterTea

+1

これは複雑すぎます。標準的なイディオムは 'lambda'または' partial'を使います。 'widget.signal.connect(lambda:func(arg1、arg2))'です。 – ekhumoro

+0

ありがとう、@ echumoro。私はlambdaを使うようにデモを更新しました。私はなぜQSignalMapperが行く方法であると思ったのか分かりません。 – Crispin

関連する問題