37 Stimmen

PyQt und MVC-Muster

Ich versuche, ein MVC-Muster mit PyQt zu entwerfen. Ich möchte alle Programme in 3 Teile aufteilen:

  1. von allen Qt-Klassen abstrahierte Klassen (Modell)
  2. Klassen, die Daten aus dem Modell an eine Qt-Anwendung (Controller) liefern
  3. die Qt-Anwendung selbst mit definierter Methode SignalsToSlots der die Signale mit dem Steuergerät verbindet.

Ist das optimal? Welches Schema wird für die Verwendung in der PyQt-Entwicklung empfohlen?

48voto

cmaynard Punkte 2751

Eines der ersten Dinge, die Sie tun sollten, ist Qt4 Designer zu verwenden, um Ihre GUI zu entwerfen und pyuic4 zu verwenden, um Ihre Python-GUI zu generieren. Dies wird Ihre Ansicht sein, Sie werden diese Python-Dateien NIEMALS von Hand bearbeiten. Nehmen Sie Änderungen immer mit dem Designer vor, so ist sichergestellt, dass Ihre View von Ihrem Model und Control getrennt ist.

Erstellen Sie für das Steuerelement eine zentrale Klasse, die von Ihrem Basis-GUI-Widget wie QMainWindow erbt. Dieses Objekt wird dann enthalten ein Mitglied ui, die Ihre Ansicht Objekt, das Sie gerade generiert ist.

Hier ist ein Beispiel aus eine Anleitung

UPDATE 2013: Hier ist ein neueres Tutorial über PyQt und MVC Model PyQt MVC Lehrgangsreihe

import sys
from PyQt4 import QtCore, QtGui
from edytor import Ui_notepad

class StartQT4(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_notepad()
        self.ui.setupUi(self)

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = StartQT4()
    myapp.show()
    sys.exit(app.exec_())

Der entscheidende Punkt im obigen Beispiel ist, dass der Controller die Benutzeroberfläche enthält und sie nicht direkt erbt. Der Controller ist für die Verwaltung von Signalsteckplatzverbindungen für die Benutzeroberfläche und die Bereitstellung einer Schnittstelle zu Ihrem Datenmodell verantwortlich.

Um den Modellteil zu beschreiben, benötigen wir ein Beispiel. Nehmen wir an, Ihr Projekt besteht darin, eine Datenbank für Filmsammlungen zu erstellen. Das Modell würde die internen Objekte enthalten, die einzelne Filme darstellen, sowie Objekte, die Listen von Filmen repräsentieren. Ihr Steuerelement würde die von der Ansicht eingegebenen Daten entgegennehmen, die Signale abfangen und sie dann validieren, bevor das Modell aufgefordert wird, sich selbst zu aktualisieren. Dieser Teil ist entscheidend, der Controller sollte nicht direkt auf das Modell zugreifen, wenn überhaupt möglich, sollte es das Modell bitten, sich selbst zugreifen.

Hier ist ein kleines Beispiel dieser Interaktion (nicht getestet, kann einige Tippfehler enthalten):

class Movie():
    def __init__(self,title=None,year=None,genre=None):
        self.title=title
        self.year=year
        self.genre=genre
    def update(self,title=None,year=None,genre=None):
        self.title=title
        self.year=year
        self.genre=genre
    def to_xml(self,title=None,date=None,genre=None):
        pass #not implementing this for an example!

#when the controller tries to update it should use update function
movie1.update("Manos Hands Of Fate",1966,"Awesome")
#don't set by direct access, your controller shouldn't get that deep
movie1.title="Bad Idea" #do not want!

In MVC ist es auch wichtig, den Zugriff zu zentralisieren, d.h. der Benutzer kann den Titel durch Doppelklick auf dem Bildschirm oder durch Klicken auf "Bearbeiten" neben dem Titelfeld ändern, beide dieser Schnittstellen sollten am Ende die gleiche Methode für die Änderung verwenden. Und damit meine ich nicht, dass jede dieser Schnittstellen movie.update_title(title) aufruft. Ich meine, dass beide Signale die gleiche Methode im Controller verwenden sollten.

Versuchen Sie so weit wie möglich, alle Beziehungen zwischen der Ansicht und dem Controller viele zu 1 zu machen. Das bedeutet, dass Sie 5 Möglichkeiten haben, etwas in der Benutzeroberfläche zu ändern, haben 1 Methode in der Steuerung, dies zu behandeln. Wenn die Slots nicht alle kompatibel sind, erstellen Sie Methoden für jede der Methoden, die dann eine einzige Methode aufrufen. Wenn Sie das Problem lösen 5 mal für 5 Ansichtsstile dann gibt es wirklich nicht und Grund, um die Ansicht von der Steuerung zu trennen. Da Sie jetzt nur eine Möglichkeit haben, etwas im Controller zu tun, haben Sie eine schöne 1 zu 1 Beziehung zwischen Control und Model.

Was die vollständige Trennung Ihres Modells von Qt betrifft, so ist dies nicht wirklich notwendig und kann Ihnen das Leben sogar erschweren. Mit Dingen wie QStrings in Sie Modell kann bequem sein, und wenn in einer anderen Anwendung, die Sie nicht wollen, den Overhead eines Gui aber die Modelle nur importieren QtCore. Hoffentlich hilft das!

9voto

abbot Punkte 26222

Ja, PyQt verwendet das Model/View-Konzept (offiziell ohne den "Controller"-Teil), aber vielleicht haben Sie ein etwas verzerrtes Bild davon, was es in PyQt bedeutet.

Sie besteht aus zwei Teilen:

  1. Modelle, die von den entsprechenden abstrakten PyQt-Basismodellklassen abgeleitet sind ( QAbstractItemModel , QAbstractTableModel , QAbstractListModel , usw.). Diese Modelle können direkt mit Ihren Datenquellen (Dateien, Datenbanken) kommunizieren oder Ihre eigenen PyQt-agnostischen Modelle, die zuvor geschrieben wurden, ersetzen.
  2. Ansichten, die in der Qt-Bibliothek implementiert sind und oft keine Änderungen erfordern (Beispiele: QTreeView , QTableView und andere). Auch einige einfachere Kontrollen, wie QComboBox kann als Ansicht für ein PyQt-Modell dienen.

Alle anderen Teile Ihrer Anwendung, die auf Signale usw. reagieren, können als "Controller" betrachtet werden.

PyQt bietet auch eine Reihe von vordefinierten "universellen" Modellen, die unterklassifiziert oder direkt verwendet werden können, wenn Sie nur einfache Funktionen des Modells benötigen, wie QStringListModel , QStandardItemModel , usw. Und es gibt auch Modelle, die direkt mit Datenbanken kommunizieren können, wie QSqlTableModel .

7voto

Jayesh Punkte 48937

Hier ist ein Link zur offiziellen und detaillierten Anleitung, wie die Qt-Architektur Model-View-Design für eine Anwendung bietet

http://doc.qt.io/qt-5/model-view-programming.html

In Qt sind View und Controller kombiniert, daher kann eine Anwendung mit einem Model-View-Framework entwickelt werden.

Das Modell kommuniziert mit einer Quelle von Da für die anderen Komponenten der Architektur. [ ] Kommunikation hängt von der Art der Datenquelle und der Art und Weise ab, wie die Modell implementiert ist. Die Ansicht erhält Modellindizes vom Modell; Dies sind Verweise auf Datenelemente. Durch die Bereitstellung von Modellindizes an kann die Ansicht Datenelemente aus der Datenquelle abrufen. In Standardansichten rendert ein Delegat die Datenelemente. Wenn ein Element bearbeitet wird, kommuniziert der Delegat direkt mit dem Modell mittels Modell-Indizes.

...

Modelle, Ansichten und Delegierte kommunizieren über Signale und Slots miteinander

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X