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:
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). 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% 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
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:
Tags und Links qt model-view-controller signals-slots