PyQtのMVCパターンの実装

すべての人に良い一日を!

この記事では、PyQtを使用するアプリケーションのMVC設計パターンの実装について、2つの数字の加算プログラムの例を使用して説明します。 パターンの実装の説明に加えて、アプリケーション作成プロセスの説明が提供されます。



0はじめに



MVC-データモデル、アクションの表示と処理を効果的に分離できる設計パターン。 MVCには、 オブザーバー戦略、 レイアウトの 3つのデザインパターンが含まれています 。 この記事では、Eric Freemanの著書Design Patternsに記載されているアクティブなモデルを使用した古典的なMVCスキームについて説明します。



さらに作業を行うには、次のものが必要です。



1プロジェクト構造



SimpleMVCプロジェクトを呼び出しましょう 。 タスクがそれほど簡単ではないように、 ABではなく、 CDを追加します プロジェクトは4つのモジュールで構成されています。 ModelController、およびViewモジュールは、それぞれモデルコントローラー、およびビューの実装を表します。 ユーティリティモジュールにはヘルパークラスが含まれています。 main.pywファイル 、アプリケーションを実行するように設計されています。



  SimpleMVC \
    コントローラー\
         __init__.py
         CplusDController.py
    モデル\
         __init__.py
         CplusDModel.py
    ユーティリティ\
         __init__.py
         CplusDMeta.py
         CplusDObserver.py
     \を表示
         __init__.py
         CplusDView.py
         MainWindow.py
         MainWindow.ui
     main.pyw 




2モデルの作成



モデル(最初に!)は、アプリケーションロジックを担当します。 CplusDModelのタスクは、2つの数字を追加することです。 CplusDModel.pyファイル:



class CplusDModel: """  CplusDModel     .      c, d   .   ,       .    ,    . """ def __init__( self ): self._mC = 0 self._mD = 0 self._mSum = 0 self._mObservers = [] #   @property def c( self ): return self._mC @property def d( self ): return self._mD @property def sum( self ): return self._mSum @c.setter def c( self, value ): self._mC = value self._mSum = self._mC + self._mD self.notifyObservers() @d.setter def d( self, value ): self._mD = value self._mSum = self._mC + self._mD self.notifyObservers() def addObserver( self, inObserver ): self._mObservers.append( inObserver ) def removeObserver( self, inObserver ): self._mObservers.remove( inObserver ) def notifyObservers( self ): for x in self._mObservers: x.modelIsChanged()
      
      







モデルはオブザーバーパターンを実装します。 これは、クラスがオブザーバーの追加、削除、警告の機能をサポートする必要があることを意味します。 さらに、モデルはコントローラーと表現から完全に独立しています。

登録されたすべてのオブザーバーは、通知されたときにモデルによって呼び出される特定のメソッドを実装することが重要です(この場合、これはmodelIsChanged()メソッドです)。 これを行うには、オブザーバーは抽象クラスの子孫でなければならず、それを継承して、 modelIsChanged()メソッドを再定義する必要があります。 CplusDObserver.pyファイル:



 from abc import ABCMeta, abstractmethod class CplusDObserver( metaclass = ABCMeta ): """     . """ @abstractmethod def modelIsChanged( self ): """         . """ pass
      
      







もちろん、「非常に柔軟なpython」を使用すると、抽象スーパークラスをまったく使用せずに、またはトリッキーなNotImplementedError()例外を使用できます。 私の意見では、これはアプリケーションのアーキテクチャに悪影響を与える可能性があります。

PyQtを使用すると、スロット信号モデルを使用できることに注意してください。 この場合、状態が変わると、接続されたすべてのオブザーバーが受信できる信号がモデルによって送信されます。 このアプローチはあまり一般的ではないようです-おそらく将来、別のライブラリを使用したくなるでしょう。

より複雑なシステムでは、オブザーバーパターン(登録、削除、オブザーバーの通知)を実装する機能は、別個の抽象クラスに区別できます。 アーキテクチャによっては、クラスは抽象的ではない場合があります。



3ビューを作成する



ビューはグラフィカルコンポーネントの組み合わせであり、リンカーパターンを実装します。 ビューを作成するには、PyQtに含まれているビジュアルエディターDesignerを使用します。 MainWindowに基づいてフォームを作成します。 形状構造:



  MainWindow-QMainWindow
     CentralWidget-QWidget
         lbl_equal-QLabel
         lbl_plus-QLabel
         le_c-QLineEdit
         le_d-QLineEdit
         le_result-QLineEdit 




フォームの外観:







フォームをプレビューするには、Ctrl + Rを使用します。 MainWindow.uiという名前でViewディレクトリにファイルを保存します。 次に、 それに基づいてMainWindow.pyファイルを生成します。 これを行うには、 pyuic4.bat (... \ Python32 \ Lib \ site-packages \ PyQt4)を使用します。 実行:



  pyuic4.bat ... \ SimpleMVC \ View \ MainWindow.ui -o ... \ SimpleMVC \ View \ MainWindow.py 




「...」の代わりに、プロジェクトのあるディレクトリへのパスを追加する必要があります。 たとえば、フルパスは次のようになります。



  D:\ Projects \ PythonProjects \ SimpleMVC \ View \ MainWindow.ui 




プロジェクトにリソースファイルが存在する場合、それを変換するには、 pyrcc4.exe (... \ Python32 \ Lib \ site-packages \ PyQt4)を使用する必要があります。 Python 3.xの場合、-py3フラグを渡す必要があります。



  pyrcc4.exe -o ... \ SimpleMVC \ View \ MainWindow_rc.py -py3 ... \ SimpleMVC \ View \ MainWindow_rc.qrc 




「_rc」に注意してください。 実際、リソースファイルがフォームに接続されている場合、pyuic4.batはファイルの最後に自動的に追加されます。



 import MainWindow_rc
      
      







次に、ビュークラスを作成する必要があります。 MVCアーキテクチャによれば、ビューはオブザーバーでなければなりません。 CplusDView.pyファイル:



 from PyQt4.QtGui import QMainWindow, QDoubleValidator from PyQt4.QtCore import SIGNAL from Utility.CplusDObserver import CplusDObserver from Utility.CplusDMeta import CplusDMeta from View.MainWindow import Ui_MainWindow class CplusDView( QMainWindow, CplusDObserver, metaclass = CplusDMeta ): """      CplusDModel. """ def __init__( self, inController, inModel, parent = None ): """       . """ super( QMainWindow, self ).__init__( parent ) self.mController = inController self.mModel = inModel #    self.ui = Ui_MainWindow() self.ui.setupUi( self ) #      self.mModel.addObserver( self ) #      self.ui.le_c.setValidator( QDoubleValidator() ) self.ui.le_d.setValidator( QDoubleValidator() ) #        self.connect( self.ui.le_c, SIGNAL( "editingFinished()" ), self.mController.setC ) self.connect( self.ui.le_d, SIGNAL( "editingFinished()" ), self.mController.setD ) def modelIsChanged( self ): """     .     . """ sum = str( self.mModel.sum ) self.ui.le_result.setText( sum )
      
      







ビューは、 QMainWindowCplusDObserverの 2つのクラスの子孫であることに注意してください。 両方のクラスは異なるメタクラスを使用します。 したがって、 CplusDViewクラスの場合 、QMainWindowおよびCplusDObserverで使用されるメタクラスを継承するメタクラスを設定する必要あります 。 この場合、それはCplusDMetaです。 CplusDMeta.pyファイル:



 """   ,    . pyqtWrapperType -      Qt. ABCMeta -     . CplusDMeta -   . """ from PyQt4.QtCore import pyqtWrapperType from abc import ABCMeta class CplusDMeta( pyqtWrapperType, ABCMeta ): pass
      
      







4コントローラーの作成



コントローラーはパターン戦略を実装します。 コントローラーはビューに接続して、アクションを制御します。 この場合、コントローラーの実装は非常に簡単です。 CplusDController.pyファイル:



 from View.CplusDView import CplusDview class CplusDController(): """  CplusDController   .     . """ def __init__( self, inModel ): """     .     . """ self.mModel = inModel self.mView = CplusDview( self, self.mModel ) self.mView.show() def setC( self ): """        C,    c . """ c = self.mView.ui.le_c.text() self.mModel.c = float( c ) def setD( self ): """        D,    d . """ d = self.mView.ui.le_d.text() self.mModel.d = float( d )
      
      







5コンポーネントの接続



すべてのコンポーネントを結合し、プログラムをチェックします。 Main.pywファイル:



 import sys from PyQt4.QtGui import QApplication from Model.CplusDModel import CplusDModel from Controller.CplusDController import CplusDController def main(): app = QApplication( sys.argv ) #   model = CplusDModel() #         controller = CplusDController( model ) app.exec() if __name__ == '__main__': sys.exit( main() )
      
      







ご清聴ありがとうございました!


ソースコード



All Articles