Warum missbraucht Qt die Modell- / Ansichtsterminologie?


104

Ich denke, dass die in Qt mit Modell- / Ansichtssteuerelementen verwendete Terminologie fehlerhaft ist. Auf ihrer Erklärungsseite geben sie an, dass sie die MVC zu MV vereinfacht haben, indem sie View und Controller zusammengeführt haben, und sie geben das folgende Bild:

Bild zur Erklärung von Qt MVC

Wie auch immer ich denke, sie haben die Rollen von Objekten falsch benannt und ich denke, dass

  1. Was sie Ansicht mit zusammengeführtem Controller nennen, ist in der Tat nur eine Ansicht.
  2. Was sie Model nennen, ist in der Tat nur Controller.
  3. Wenn Sie wirklich ein Modell haben möchten, ist es irgendwo, wo sich ihre "Daten" befinden.

Ich spreche von der üblichen und vernünftigen Art und Weise, wie Sie die Qt-Modell- / Ansichtskomponente in Ihrer App verwenden würden. Hier sind die Gründe:

  1. Dies ist normalerweise eine Qt-Komponente, die unverändert verwendet wird, ohne dass eine für Ihre Objekte spezifische Controller-Logik hinzugefügt wird.
  2. Dies ist kaum ein Modell, nur weil Sie mehrere Qt-Methoden wie rowCount, columnCount, data usw. implementieren sollten, die nichts mit Ihrem Modell zu tun haben. Tatsächlich gibt es typische Modellmethoden in Controllern. Natürlich können Sie hier sowohl Controller- als auch Modelllogik implementieren , aber erstens wäre es ein ziemlich schlechtes Code-Design und zweitens würden Sie Controller und Modell zusammenführen, nicht Controller und View, wie sie angeben.
  3. Wie in Grund 2 gesagt, wenn Sie die Modelllogik trennen möchten, ist dies sicherlich nicht das blaue Feld auf dem Bild, sondern das gestrichelte Feld "Daten" (Kommunikation mit realen Daten natürlich).

Ist Qt in ihrer Terminologie falsch oder bin es nur ich, der es nicht versteht? (Übrigens: Der Grund, warum es keine akademische Frage ist, ist, dass ich begonnen habe, mein Projekt nach ihrer Benennung zu codieren, und ich habe bald herausgefunden, dass der Code eindeutig nicht richtig ist. Erst danach wurde mir klar, dass ich es tun sollte nicht versuchen, Modelllogik in das zu setzen, was sie Modell nennen)


1
MFC setzte den Standard für zweiteilige Modell- / Ansichts-Guis mit CDoc und CView - es gibt keinen Grund, warum eine bestimmte MVC "korrekt" ist
Martin Beckett,

@ Martin B: Ich werde einen Blick auf MFC werfen, aber selbst wenn es verschiedene MVC-Modelle gibt, denke ich, dass sie in ihrer Terminologie konsistent sein sollten, und ich denke, ich habe gültige Argumente vorgelegt, warum die verwendete Terminologie in diesem speziellen Fall nicht konsistent ist. Sie geben einfach an, dass sie View und Controller kombiniert haben, aber ich denke, dass dies in diesem Fall einfach irreführend ist. Ich glaube nicht, dass es ein MVC-Modell gibt, bei dem die gesamte anwendungsspezifische Logik, sei es Präsentation oder Modelllogik, in ein Objekt namens Modell eingefügt werden muss.
Gorn

1
@Martin B: Auch unter der qt-Terminologie haben alle Modelle eine gemeinsame API, die nichts mit der Modellstruktur zu tun hat, sondern alles mit der allgemeinen Controller-Struktur, was eindeutig ein Zeichen dafür ist, dass es nicht richtig ist, sie Modell zu nennen. Ich sage nicht, dass es EIN korrektes MVC-Modell gibt, aber es bedeutet nicht, dass irgendetwas als MVC-Modell bezeichnet werden kann. Vielleicht ist es auch in MFC fehlerhaft und ich kann es mir ansehen, aber ich bin mehr daran interessiert, es richtig zu machen, diesen MFC, den ich nicht verwenden möchte. Haben Sie einen guten Link, über den die Trennung von MFC-Modell und Ansicht erklärt wird?
Gorn

1
Die MVC-Terminologie wird keineswegs einstimmig vereinbart, sodass Ihre Frage als argumentativ angesehen werden kann. Viele werden jedoch der hervorragenden Arbeit von Martin Fowler ( martinfowler.com/eaaDev/index.html ) zustimmen . Normalerweise verarbeitet der Controller Benutzereingaben, und in diesem Sinne kombinieren Qt-Widgets definitiv Ansicht und Controller.
Arnold Spence

1
Ich verstehe, dass MVC viele Geschmacksrichtungen hat, aber das bedeutet nicht, dass alles MVC sein kann. Qt hat die Grenze überschritten und ich habe mehrere Gründe angegeben. Martin Fowler erklärt zwar verschiedene Arten von MVC, aber keiner von ihnen ähnelt dem, was Qt MVC ausspricht. Am ähnlichsten ist martinfowler.com/eaaDev/PresentationModel.html , dies unterscheidet jedoch zwischen Presentation Model = Controller (Benutzerinteraktion) und Model (Datenlogik). Obwohl es keine genaue Definition von MVC gibt, folgt Qt keiner von ihnen. Wenn Sie mir einen Link zu einer solchen Definition geben können, tun Sie dies bitte.
Gorn

Antworten:


78

Ich stimme Ihnen zu, dass die Benennung von Qt irreführend ist. Meiner Meinung nach liegt das Problem jedoch nicht nur bei Qt, sondern wird von allen Frameworks geteilt, die es uns ermöglichen, bei der Implementierung unserer Benutzeroberflächen das Prinzip der Trennung von Bedenken einzuhalten. Wenn jemand ein solches Framework entwickelt und einen guten Weg findet, um "Dinge" getrennt zu halten, fühlt er sich immer verpflichtet, Module zu haben, die er "Modell" nennt, und andere, die er "Ansicht" nennt. Im Laufe der Jahre habe ich mit folgenden Frameworks gearbeitet:

  • MFC
  • Qt
  • Schwingen
  • SWT
  • WPF mit MVVM

Wenn Sie vergleichen, wie die Begriffe "Modell" und "Ansicht" in diesen Frameworks verwendet werden und welche Verantwortlichkeiten die Klassen in "Ansicht", "Modell" und "Controller" (falls vorhanden) haben, werden Sie finde, dass es sehr große Unterschiede gibt. Es wäre sicherlich nützlich, die verschiedenen Konzepte und Terminologien zu vergleichen, damit Menschen, die von einem Framework zu einem anderen wechseln, die Möglichkeit haben, gesund zu bleiben, aber das würde viel Arbeit und Forschung erfordern. Eine gute Lektüre ist Martin Fowlers Übersicht .

Da es so viele verschiedene Ideen gibt, wie ein MVC-Muster aussehen kann, welches ist richtig? Meiner Meinung nach sollten sich die Leute, die MVC erfunden haben, an uns wenden, wenn wir wissen wollen, wie es "richtig" implementiert werden soll. Auf dem Original-Smalltalk-Papier steht:

Die Ansicht verwaltet die grafische und / oder Textausgabe für den Teil der Bitmap-Anzeige, der ihrer Anwendung zugeordnet ist. Die Steuerung interpretiert die Maus- und Tastatureingaben des Benutzers und befiehlt dem Modell und / oder der Ansicht, diese entsprechend zu ändern. Schließlich verwaltet das Modell das Verhalten und die Daten der Anwendungsdomäne, antwortet auf Informationsanfragen zu ihrem Status (normalerweise aus der Ansicht) und auf Anweisungen zum Ändern des Status (normalerweise vom Controller).

In Anbetracht dessen würde ich Ihre drei Hauptanliegen folgendermaßen beantworten:

  1. Tatsächlich verwaltet eine Qt-Komponente "die grafische [...] Ausgabe" und "interpretiert die Maus- und Tastatureingaben", so dass sie in Bezug auf die obige Definition tatsächlich als zusammengeführte Ansicht und Steuerung bezeichnet werden kann.
  2. Ich bin damit einverstanden, dass Sie gezwungen sind / wären, Controller und Modell zusammenzuführen (wiederum in Bezug auf die obige Definition).
  3. Ich stimme wieder zu. Das Modell sollte nur die Daten der Anwendungsdomäne verwalten . Dies ist, was sie "Daten" nennen. Natürlich hat der Umgang mit Zeilen und Spalten normalerweise nichts mit unserer Anwendungsdomäne zu tun.

Wo bleibt es uns? Meiner Meinung nach ist es am besten herauszufinden, was Qt wirklich bedeutet, wenn die Begriffe "Modell" und "Ansicht" verwendet werden, und die Begriffe auf ihre Weise zu verwenden, während wir mit Qt programmieren. Wenn Sie sich weiterhin Sorgen machen, wird dies Sie nur verlangsamen, und die Art und Weise, wie die Dinge in Qt eingerichtet sind, ermöglicht ein elegantes Design - das mehr wiegt als ihre "falschen" Namenskonventionen.


2
Ich würde sagen, dass der Delegat der Controller des Qt ist, da die Delegierten die Eingabe empfangen und an das Modell senden, wodurch die Ansicht durch Signale aktualisiert wird.
Peregring-lk

82

Kurze Antwort

Die MVC von Qt gilt nur für eine Datenstruktur . Wenn Sie über eine MVC- Anwendung sprechen , sollten Sie nicht an QAbstractItemModeloder denken QListView.

Wenn Sie eine MVC-Architektur für Ihr gesamtes Programm wünschen, hat Qt kein so "riesiges" Modell- / Ansichts-Framework. Für jede Liste / jeden Datenbaum in Ihrem Programm können Sie jedoch den Qt MVC-Ansatz verwenden, für den tatsächlich ein Controller angezeigt wird. Die Daten befinden sich innerhalb oder außerhalb des Modells. Dies hängt davon ab, welchen Modelltyp Sie verwenden (eigene Modellunterklasse: wahrscheinlich innerhalb des Modells; z. B. QSqlTableModel: außerhalb (aber möglicherweise innerhalb des Modells zwischengespeichert)). Verwenden Sie zum Zusammenstellen Ihrer Modelle und Ansichten eigene Klassen, die dann die Geschäftslogik implementieren .


Lange Antwort

Qts Modell- / Ansichtsansatz und Terminologie:

Qt bietet einfache Ansichten für ihre Modelle. Sie haben einen eingebauten Controller : Das Auswählen, Bearbeiten und Verschieben von Elementen ist etwas, was ein Controller in den meisten Fällen "steuert". Das heißt, Benutzereingaben interpretieren (Mausklicks und Bewegungen) und dem Modell die entsprechenden Befehle geben.

Die Modelle von Qt sind in der Tat Modelle mit zugrunde liegenden Daten. Die abstrakten Modelle enthalten natürlich keine Daten, da Qt nicht weiß, wie Sie sie speichern möchten. Aber Sie einen QAbstractItemModel auf Ihre Bedürfnisse erweitern , indem Sie Ihre Datencontainer an die Unterklasse hinzufügen und machen das Modell Schnittstelle Ihre Daten zugreifen kann . In der Tat, und ich nehme an, dass Ihnen das nicht gefällt, besteht das Problem darin, dass Sie das Modell programmieren müssen, damit auf Daten in Ihrer Datenstruktur zugegriffen und diese geändert werden können.

In der MVC-Terminologie enthält das Modell sowohl die Daten als auch die Logik . In Qt liegt es an Ihnen, ob Sie einen Teil Ihrer Geschäftslogik in Ihr Modell aufnehmen oder nach außen stellen, um eine "Ansicht" für sich zu sein. Es ist nicht einmal klar, was unter Logik zu verstehen ist: Elemente auswählen, umbenennen und verschieben? => bereits implementiert. Berechnungen mit ihnen machen? => Platzieren Sie es außerhalb oder innerhalb der Modellunterklasse. Daten aus / in eine Datei speichern oder laden? => Fügen Sie es in die Modellunterklasse ein.


Meine persönliche Meinung:

Es ist sehr schwierig , einem Programmierer ein gutes und allgemeines MV (C) -System bereitzustellen . Da die Modelle in den meisten Fällen einfach sind (z. B. nur Zeichenfolgenlisten), bietet Qt auch ein gebrauchsfertiges QStringListModel. Wenn Ihre Daten jedoch komplexer als Zeichenfolgen sind, liegt es an Ihnen, wie Sie die Daten über die Qt-Modell- / Ansichtsschnittstelle darstellen möchten. Wenn Sie beispielsweise eine Struktur mit 3 Feldern haben (z. B. Personen mit Name, Alter und Geschlecht), können Sie die 3 Felder 3 verschiedenen Spalten oder 3 verschiedenen Rollen zuweisen. Ich mag beide Ansätze nicht.

Ich denke, das Modell- / Ansichts-Framework von Qt ist nur nützlich, wenn Sie einfache Datenstrukturen anzeigen möchten . Es wird schwierig zu handhaben, wenn die Daten benutzerdefinierte Typen haben oder nicht in einem Baum oder einer Liste (z. B. einem Diagramm) strukturiert sind. In den meisten Fällen reichen Listen aus, und selbst in einigen Fällen sollte ein Modell nur einen einzigen Eintrag enthalten. Insbesondere wenn Sie einen einzelnen Eintrag mit unterschiedlichen Attributen (eine Instanz einer Klasse) modellieren möchten, ist das Modell- / Ansichts-Framework von Qt nicht der richtige Weg, um Logik von der Benutzeroberfläche zu trennen.

Zusammenfassend denke ich, dass das Modell- / Ansichts-Framework von Qt genau dann nützlich ist, wenn Ihre Daten von einem der Viewer-Widgets von Qt angezeigt werden . Es ist völlig nutzlos, wenn Sie einen eigenen Viewer für ein Modell schreiben möchten, das nur einen Eintrag enthält, z. B. die Einstellungen Ihrer Anwendung, oder wenn Ihre Daten nicht druckbar sind.


Wie habe ich das Qt-Modell / die Qt-Ansicht in einer (größeren) Anwendung verwendet?

Ich habe einmal (in einem Team) eine Anwendung geschrieben, die mehrere Qt-Modelle zum Verwalten von Daten verwendet. Wir haben uns entschlossen, ein zu erstellen DataRole, um die tatsächlichen Daten zu speichern, die für jede Modellunterklasse einen anderen benutzerdefinierten Typ hatten. Wir haben eine äußere Modellklasse erstellt, Modeldie alle verschiedenen Qt-Modelle enthält. Wir haben auch eine äußere Ansichtsklasse erstellt, Viewdie die Fenster (Widgets) enthält, die mit den darin enthaltenen Modellen verbunden sind Model. Dieser Ansatz ist also eine erweiterte Qt-MVC, die an unsere eigenen Bedürfnisse angepasst ist. Beide Modelund ViewKlassen selbst haben nichts mit der Qt MVC zu tun.

Wo haben wir die Logik hingelegt ? Wir haben Klassen erstellt, die die eigentlichen Berechnungen für die Daten durchgeführt haben, indem wir Daten aus Quellmodellen gelesen haben (wenn sie sich geändert haben) und die Ergebnisse in Zielmodelle geschrieben haben. Aus Sicht von Qt wären diese Logikklassen Ansichten, da sie sich mit Modellen "verbinden" (nicht "Ansicht" für den Benutzer, sondern eine "Ansicht" für den Geschäftslogik-Teil der Anwendung).

Wo sind die Controller ? In der ursprünglichen MVC-Terminologie interpretieren Controller die Benutzereingaben (Maus und Tastatur) und geben dem Modell Befehle, um die angeforderte Aktion auszuführen. Da die Qt-Ansichten bereits Benutzereingaben wie das Umbenennen und Verschieben von Elementen interpretieren, war dies nicht erforderlich. Was wir jedoch brauchten, war eine Interpretation der Benutzerinteraktion, die über die Qt-Ansichten hinausgeht.


Das Irritierendste ist, dass Sie je nach gewünschter Ansicht völlig unterschiedliche Qt-Modellklassen implementieren müssen. Ein Modell für eine Listenansicht unterstützt eine Baumansicht nicht ordnungsgemäß und umgekehrt. Ein kanonisches MVC-Modell kann eine Vielzahl verschiedener Ansichtstypen unterstützen.
Smerlin

3
@smerlin: Ich denke nicht, dass das richtig ist. Sowohl ein QListView als auch ein QTreeView erfordern nur eine QAbstractItemView-Schnittstelle, was bedeutet, dass eine benutzerdefinierte Unterklasse davon oder eine konkrete Klasse wie QStandardItemModel diese Anforderung für beide erfüllen sollte. Sie können einen Baum fahren und ein Modell auflisten.
JDI

1
@jdi: Es gibt Fälle, in denen Ihre Daten sowohl eine Liste als auch ein Baum sind ... z. B. möchten Sie Ihr Dateisystem als Baum oder alle Dateien als Liste anzeigen. Qts-Modelle erlauben das nicht richtig. Bei einer Implementierung von QAbstractItemModel, die Baumansichten unterstützt, können nur alle Dateien / Verzeichnisse in Ihrem Stammverzeichnis als Liste angezeigt werden, Sie können jedoch nicht alle Dateien als Liste anzeigen. Und sagen Sie nicht, dass das Anzeigen von Baumdaten als Liste nicht nützlich sein kann. Sie können sie beispielsweise einfach sortieren, um die Datei mit der größten Dateigröße zu finden, wenn Sie Ihre Dateien als Liste anzeigen. Baumansichten würden dies nicht zulassen.
smerlin

1
Wie gesagt, ist das Proxy - Modell mehr etwas von Ihrer Sicht (da es ändert , wie die Daten angezeigt ) und somit zu Ihrer Ansicht gehören soll. Wenn Sie meine lange Antwort lesen: In der "großen" ViewKlasse sollten Sie das Proxy-Modell hinzufügen, das das Baummodell als zugrunde liegendes Modell hat und von Ihrer Dateisystem-Listenansicht verwendet wird. Wie Sie sagen: Es sollten keine zwei Modelle für dieselben Daten vorhanden sein. Noch nie! (Aber Proxy-Modelle zählen nicht als separate Modelle.)
Leemes

1
@ SamPinkus Das liegt daran, dass es zu dieser Frage kein klares Ja oder Nein gibt. Es gibt auch verschiedene Implementierungen von QAbstractItemModel, von denen einige Modelle im Sinne von MVC sind und einige nicht.
Leemes

12

Die Terminologie ist nicht richtig oder falsch, sie ist nützlich oder nutzlos.

Sie können die Frage ein wenig ändern und fragen, warum Qt nicht MVC-freundlicher ist. Die Antwort darauf ist, dass die frühen Qt-Entwickler glauben, dass das Entkoppeln von V von C in GUI-Anwendungen zu schlechten Vs und Cs führt. Das Design von QWidget versucht, es einfach zu machen, die Interferenz der Mauseingaben eng mit den Entscheidungen zur Pixelausgabe zu verknüpfen, und Sie können sehen, dass dies nicht der Weg zu MVC ist.


Ich verstehe Ihren Standpunkt und im Grunde würde ich fragen, warum Qt nicht MVC-freundlicher ist, aber es ist sehr schwierig, wenn die in der Qt-Dokumentation verwendete MVC-Terminologie von der normalerweise verwendeten MVC-Terminologie abweicht (wie ich in der Frage erklärt habe). Und wenn es eine weit verbreitete Terminologie gibt und jemand sie ganz anders verwendet als der Rest der Welt, neige ich dazu zu denken, dass sie nicht nur nutzlos ist, sondern einfach FALSCH und verwirrend (diese Verwirrung hat mich veranlasst, die Frage in der ersten zu stellen Ort). Es würde mich sehr interessieren, wenn Sie Links zu diesen Dingen haben, die irgendwo diskutiert oder erklärt werden. Danke
gorn

Ich kann nichts darüber sagen, warum die Qt-Dokumente jetzt so über MVC sprechen, wie sie es tun. Ich habe Trolltech vor langer Zeit verlassen und bin verwirrt über einige Dinge, die seit meiner Abreise an der Dokumentation vorgenommen wurden. (Auf meinem Blog schimpfe ich manchmal ein bisschen darüber.)
arnt

Haben Sie einen Einblick, wie die MVC-Terminologie in Qt vereinbart wurde? Wurde es beim Schreiben des Codes oder erst später während des Dokumentationsprozesses verwendet?
Gorn

Während meiner Zeit bei Trolltech haben wir das Wort "MVC" in der Qt-Dokumentation nicht verwendet. Im Allgemeinen denke ich, dass es am besten ist, zu dokumentieren, was da ist, und nicht darüber zu schreiben, was nicht da ist. Bei gitorious können Sie jedoch herausfinden, wer diesen Text hinzugefügt hat, und diese Person direkt hinzufügen.
arnt

1
Ein anderer Kommentar. Wir haben MVC während des Entwurfs und der frühen Implementierung von Qt (als Trollech ein Drei-Personen-Unternehmen war) besprochen und ein GUI-Toolkit evaluiert, das MVC "richtig" verwendete. Ich kann mich nicht an seinen Namen erinnern. Wir waren der Meinung, dass die Verwendung dieses Toolkits schrecklich war und dass MVC ein wesentlicher Grund dafür war.
arnt

3

Als Modellfunktion reagiert auf Anfragen nach Informationen, denke ich nichts falsch es bei der Festlegung solcher Verfahren wie rowCount, columnCountetc. Ich denke Modell eine Art Wrapper für Datenquelle (egal , was es ist SQL - Tabelle oder ein Array) Es stellt Daten in Standardform bereit, und Sie sollten Methoden definieren, die von Ihrer Datenquellenstruktur abhängen.


2

Ich glaube, ihre Terminologie ist korrekt ... obwohl es in realen Anwendungen sehr einfach sein kann, die Grenzen zwischen Modell, Ansicht und Controller zu verwischen, abhängig von Ihrer Abstraktionsebene: Die Ansicht einer Ebene kann das Modell einer höheren Ebene sein.

Ich glaube, die Verwirrung ergibt sich aus ihrer QAbstractModelItem-Klasse. Diese Klasse ist kein Modellelement, sondern eine Schnittstelle zu einem Modell. Um ihre Ansichtsklassen mit dem Modell zu verbinden, mussten sie eine generische abstrakte Schnittstelle zum Modell erstellen. Ein Modell kann jedoch ein einzelnes Element, eine Liste von Elementen, eine Tabelle mit zwei oder mehr Dimensionen von Elementen usw. sein. Daher muss ihre Schnittstelle alle diese Modellvarianten unterstützen. Zugegeben, dies macht die Modellelemente ziemlich komplex, und der Klebercode, damit es mit einem tatsächlichen Modell funktioniert, scheint die Metapher ein wenig zu dehnen.


Obwohl ich mit der QAbstractModelItem-Klasse einverstanden bin, denke ich auch, dass ihre MVC auch ohne diese Komplikation falsch benannt ist. Können Sie erklären, warum Sie der Meinung sind, dass ihre Terminologie korrekt ist? Ich würde gerne hören, warum ich in keinem meiner drei Argumente richtig bin.
Gorn

0

Ich denke, dass ... Was sie Model nennen, ist in der Tat nur Controller.

Nein, ihr "Modell" ist definitiv kein Controller.

Der Controller ist der Teil der vom Benutzer sichtbaren Steuerelemente, die das Modell ändern (und daher indirekt die Ansicht ändern). Beispielsweise ist eine Schaltfläche "Löschen" Teil der Steuerung.

Ich denke, es gibt oft Verwirrung, weil viele so etwas wie "Der Controller modifiziert das Modell" sehen und denken, dass dies die Mutationsfunktionen ihres Modells bedeutet, wie eine "deleteRow ()" - Methode. In der klassischen MVC ist der Controller jedoch speziell der Teil der Benutzeroberfläche. Methoden, die das Modell mutieren, sind einfach Teil des Modells.

Seit der Erfindung von MVC ist die Unterscheidung zwischen Controller und Ansicht immer angespannter geworden. Denken Sie an ein Textfeld: Es zeigt Ihnen sowohl Text als auch die Möglichkeit, ihn zu bearbeiten. Ist es also eine Ansicht oder ein Controller? Die Antwort muss sein, dass es Teil von beiden ist. Als Sie in den 1960er Jahren an einem Teletyp arbeiteten, war die Unterscheidung klarer - denken Sie an die ed-, aber das bedeutet nicht, dass die Dinge für den Benutzer damals besser waren!

Es ist wahr, dass ihr QAbstractItemModel eher höher ist als ein Modell normalerweise. Zum Beispiel können Elemente darin eine Hintergrundfarbe haben (technisch gesehen ein Pinsel), was ein ausgesprochen anschauliches Attribut ist! Es gibt also ein Argument, dass QAbstractItemModel eher einer Ansicht ähnelt und Ihre Daten das Modell sind. Die Wahrheit ist, dass es irgendwo zwischen den klassischen Bedeutungen von Ansicht und Modell liegt. Aber ich kann nicht sehen, wie es ein Controller ist; Wenn überhaupt, dann ist dies das QT-Widget, das es verwendet.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.