そのため、pyqt アプリケーションで実行されているという事実を知りたくないモデル クラスがあります。しかし同時に、モデルが変更されたときに、UI を更新する必要があります。
モデルのコードに pyqt シグナルを入れたくないのです。オブザーバー パターンは、それをリッスンする 1 つのことに対してコードが多すぎるように感じます。
この問題のクリーンな解決策は何ですか?
そのため、pyqt アプリケーションで実行されているという事実を知りたくないモデル クラスがあります。しかし同時に、モデルが変更されたときに、UI を更新する必要があります。
モデルのコードに pyqt シグナルを入れたくないのです。オブザーバー パターンは、それをリッスンする 1 つのことに対してコードが多すぎるように感じます。
この問題のクリーンな解決策は何ですか?
オブザーバー パターンは、それをリッスンする 1 つのことに対してコードが多すぎるように感じます。
実際、オブザーバー パターンはまさに必要なものであり、PyQt シグナル/スロットをまったく使用する必要はありません。コードを構造化する「正しい」方法は、GUI の存在を認識しないビジネス ロジックを作成することですが、GUI にはビジネス ロジックへの (弱い) 参照が必要です。
私は通常、PyQt アプリケーションを次のように起動します。
import sys
import weakref
import PyQt4.QtGui as QtGui
from businesslogic import MyBusinessLogicClass
from guimodule import MyGuiClass
app = QtGui.QApplication(sys.argv)
business_object = MyBusinessLogicClass()
gui = MyGuiClass(weakref.proxy(business_object))
sys.exit(app.exec_())
GUI はビジネス ロジック オブジェクトへの参照を (弱い参照を介して) 受け取ることに注意してください。したがって、GUI は、人間が GUI と対話するときにビジネス ロジックにデータを送信できます。
あなたの質問は、コード内で gui への明示的な参照がなくても、ビジネス ロジックが gui にデータを取得する方法に関するものでした。GUIに知ってもらいたい関数とメソッドを配置できるデコレータを作成することで、これを解決しました。ビジネス ロジックが次のようになっているとします。
# businesslogic.py
from observed import event # Bear with me for a minute.
class MyBusinessLogicClass(object):
@event
def do_something_interesting(self, arg):
print("logic back-end did something interesting with arg=%s"%(arg,))
この小さなデコレーター@event
によって、 が呼び出されるたびに他のものがサインアップして通知を受けることができるようになりますdo_something_interesting
。guiはこれを行います
# guimodule.py
class MyGuiClass(QtGui.QMainWindow):
def __init__(self, business):
QtGui.QMainWindow.__init__(self)
self.business = business
business.do_something_interesting.addObserver(self.notify)
def notify(self, arg):
<present notification to the user>
MyBusinessLogicClass
GUIについて何も知らないことに注意してください。コードへの唯一の侵入@event
は、GUI をまったく知らず、実際には PyQt をまったく知らないデコレータでした。また、渡された が GUIの監視メソッドにarg
渡されることにも注意してください。MyBusinessLogicClass
notify
@event
わかりました、これはすべて素晴らしいことですが、そのデコレーターを取得するには、オブザーバー パターンを実装する何かの存在に依存しています。observed on GitHubと呼ばれる私の実装を入手するか、単に行うことができます
$ pip install observed
Windows を使用している場合は、github からソース ディストリビューションをダウンロードし、ルート ディレクトリで次のようにします。
> python setup.py install
これがお役に立てば幸いです。私はこのユースケースのために特別に監視を開発しました。これは非常に単純ですが、Python で見た他のオブザーバー パターンの実装のいくつかの欠点に対処しています。
注:私が観察したライブラリは開発中であるため、この投稿が書かれてから構文が少し変更されている可能性があります。
編集:カスタムクラスを変更せずにこれをすべて機能させたいと言いました。それは可能ですが、実行時にメソッドの性質を台無しにする必要があります (私が思うに)。これは、コードで直接行うよりも混乱しやすく、壊れやすいため、一般的に嫌われています。一部のメソッドにデコレータを追加するのが@event
面倒な場合は、カスタム クラスをサブクラス化し、そのサブクラスにデコレータを追加できます。カスタム メタクラスを使用してデコレータを自動的に適用することもできます。