Qt Modell / Ansicht / Controller Beispiel

8

Ich beginne gerade in Qt und versuche, ein vereinfachtes, funktionierendes Beispiel des Modell-View-Controller-Entwurfsmusters zu erhalten.

Bis jetzt war ich in der Lage, Signale und Steckplätze zu verwenden, um grundlegende Widgets wie Drucktasten mit einem QLabel zu verbinden, und die Ansicht kann geändert werden, wenn der Knopf gedrückt / losgelassen wird. Siehe Code unten für ein funktionierendes Beispiel (implementiert in der Klasse MainWindow ).

Ich versuche eine Klasse zu definieren, in diesem Fall Game , was mein Modell sein wird. Ich möchte, dass Game alle Daten und Geschäftsregeln meiner gesamten Anwendung enthält. Ich brauche nicht, dass Game irgendetwas Qt spezifisch ist - es könnte sehr gut generisches C ++ sein. Im folgenden Code ist jedoch ein Qt-spezifischer Code zum Implementieren von QTimer enthalten, der für die Zwecke dieses Beispiels nützlich ist.

Ich versuche in diesem Beispiel zwei Dinge zu erreichen:

  1. Ich möchte ein Modell haben, das in der Lage ist, irgendeine Art von Ereignis in sich selbst zu erzeugen, wie zum Beispiel einen variablen Wert im Laufe der Zeit zu erhöhen und dann letztendlich diese Veränderung in der Ansicht zu sehen. Oder noch besser, die timeout() der QTimer könnte einfach das Signal sein, das mit einem Slot verbunden ist, wobei dieser Slot ein Ereignis ist, das innerhalb des Modells stattfindet. Mit dem unten gezeigten Code wäre die Reflektion in der Ansicht die Einstellung von label_1 (Teil der Klasse MainWindow ), um eines der Bilder anzuzeigen, die bereits in imageOn oder imageOff (auch Teil der MainWindow class).
  2. Ich möchte, dass der den on_pushButton_clicked() - und on_pushButton_pressed() -Slots zugeordnete Druckknopf einen im Modell gespeicherten Wert ändern kann. Wenn der Kreis mit Punkt 1 geschlossen wird, wird das Update des Modells in der Ansicht angezeigt.

Wenn meine Terminologie bisher falsch oder nicht mit der Qt-Terminologie des MVC-Entwurfsmusters übereinstimmt, vergib mir. Ich würde jede Klarstellung dazu begrüßen. Wenn der Beispielcode, den ich zur Verfügung gestellt habe, zu kompliziert ist, um das MVC-Entwurfsmuster in Qt zu veranschaulichen, bin ich mehr als bereit, den Schiefer sauber zu wischen und mit einem geeigneteren Beispiel zu beginnen. Ich versuche nur, mit Qt und MVC zu beginnen, aber mit komplexeren Datentypen.

Ich versuche, ein Beispiel zu entwickeln, in dem ich mit einem Modell und einer Klasse wie Game umgehen kann, das möglicherweise komplex ist - keine einfache Liste von QStrings oder etwas, das garantiert geradliniger ist. Als ich die Qt-Dokumentation zu MVC durchblätterte, stieß ich auf viele Beispiele, die die Funktion setModel() benutzten, um die Verbindungen herzustellen, die ich im Wesentlichen in den Listenelementen 1 und 2 skizziere. Das Problem war, dass ich nichts sehen konnte eine Möglichkeit, diesen exakten Ansatz mit einem komplexeren Datentyp wie Game zu verwenden, der das gesamte Datenmodell für eine vollständige Anwendung sein könnte (ich weiß, dass Game in diesem Beispiel nicht komplex ist, aber es könnte irgendwann sein). Ich brauche etwas, das skalierbar und erweiterbar ist, etwas, das für eine ganze Anwendung funktionieren würde. Wenn diese setModel() -Funktionen dafür geeignet sind - was sie sehr wahrscheinlich sein könnten, ich konnte es einfach nicht selbst herausfinden - würde ich gerne wissen, wie man diese in diesem Beispiel implementiert, die sich mit QLabel befassen. und Bilder.

Code:

game.h

%Vor%

game.cpp

%Vor%

Hauptfenster.h

%Vor%

Hauptfenster.cpp

%Vor%

main.cpp

%Vor%     
nairware 16.11.2012, 19:13
quelle

1 Antwort

7

Ein "Controller" in Qt könnte technisch durch eine separate Unterklasse QObject repräsentiert werden, die nur Slots enthält. Und du würdest das zwischen deinem Modell und deiner Ansicht verkabeln.
Aber normalerweise mache ich (und sehe), dass Ihr Modell nur Geschäftslogik enthält, und Ihre View-Unterklasse enthält Methoden zur Handhabung der Benutzerinteraktionen. Am ehesten komme ich zu dem Controller-Konzept, wenn ich meine QMainWindow (oder Dialog) -Klasse habe, die die Anwendung darstellt, und eine Reihe von SLOTS darauf hat. Diese Slots werden mit den Signalen der privaten UI-Mitglieder verbunden, um sie miteinander zu verbinden.

Beispiel: Ihr Hauptfenster hat ein Modell, eine Ansicht und einen Druckknopf. In der Init für das Hauptfenster würde ich das Modell in der Ansicht festlegen und den Druckknopf "angeklickt" mit einem Steckplatz in meinem Fenster refreshData() verbinden. Dieser Slot würde dann die "update" -Methode für das Modell aufrufen, die automatisch zur Ansicht propagiert. Das Hauptfenster wirkt somit wie ein Controller.

Was Sie tun möchten, ist eine Art von QAbstractItemModel oder QStandardItemModel , die Ihre Daten darstellt und macht, was Sie diese Daten aktualisieren möchten (ein Timer wie Sie vorgeschlagen). Jede Ansicht, die mit dem Modell verbunden ist, kann sie aufgrund der Standardschnittstelle sehen. Sie können auch einen separaten Timer erstellen, der Daten in eine vorhandene QStandardItemModel

speichert

Ein Hinweis zu benutzerdefinierten QAbstractItemModel-Klassen

Wie von @hyde gezeigt, kann das Springen in ein benutzerdefiniertes Modell eine Herausforderung sein, wenn Sie es zuerst versuchen, bevor Sie ein gutes Verständnis der vorhandenen konkreten Modellklassen erhalten. Hier ist, was ich empfehle zu tun:

  1. Machen Sie sich mit den Komfort-Widgets vertraut (QListWidget, QTableWidget, QTreeWidget)
  2. Versuchen Sie dann, ein QStandardItemModel mit einer QListView / QTableView
  3. zu verwenden
  4. Dann arbeite mit QTreeView
  5. Schließlich, wenn Sie wirklich sehr benutzerdefinierte Modellierung für Ihre vorhandenen Datenstrukturen benötigen, können Sie an der Unterklasse von QAbstractItemModel arbeiten, damit diese Ihre eigene interne Struktur verwendet.
jdi 16.11.2012, 19:38
quelle