Kapitel 21. Grafische Darstellung

Kennen Sie die Situation, wenn Dutzende grafischer Objekte anfangen zu „ruckeln”, sich gegenseitig überdecken und sich unvorhersehbar verhalten? Jeder Entwickler, der mit interaktiver Grafik arbeitet, stößt früher oder später auf dieses Chaos — besonders wenn Skalierung, Drehungen, Kollisionen und Echtzeit-Event-Verarbeitung erforderlich sind.

Dieses Kapitel offenbart schrittweise, wie man eine chaotische 2D-Szene in ein verwaltbares, skalierbares System verwandelt. Hier entdecken Sie, warum professionelle Entwickler nicht auf manuelles Neuzeichnen, sondern auf eine Architektur setzen, die mühelos Tausende und sogar Millionen von Elementen verarbeiten kann. Der „Vorher/Nachher”-Kontrast ist sofort spürbar: weniger Code — mehr Kontrolle, höhere Performance und sauberere Logik.

Behandelt werden QGraphicsScene, QGraphicsView und QGraphicsItem, Arbeit mit Elementhierarchien, grundlegende Transformationen und mehrere Kollisionserkennungsmodi — von schnell bis präzise. In praktischen Beispielen wird gezeigt, wie dasselbe Objekt in mehreren Views angezeigt und auf Events reagieren kann, ohne manuelles Neuzeichnungs-Management.

Dieses Kapitel zu überspringen bedeutet das Risiko, für immer in der Welt von Workarounds und überflüssigen Optimierungen zu bleiben.

Das Kapitel enthält Code-Beispiele, die sofort einsatzbereit sind.

Selbstüberprüfung zum Kapitel

Welche Rolle erfüllt jede der drei Hauptklassen der grafischen Darstellung in der Qt-Architektur?Antwort
Richtige Antwort: QGraphicsScene ist der Modell-Container für grafische Elemente, QGraphicsView — die View zur Visualisierung mit Scrollbalken, QGraphicsItem — die abstrakte Basisklasse zur Erstellung von Szenen-Elementen.
Warum ist die Klasse QGraphicsItem abstrakt und welche Methoden müssen beim Erstellen eines eigenen Elements implementiert werden?Antwort
Richtige Antwort: QGraphicsItem ist abstrakt, um Flexibilität für verschiedene Elementtypen zu gewährleisten. Bei Vererbung müssen paint() für das Zeichnen und boundingRect() zur Bestimmung der Elementgrenzen implementiert werden.
Warum teilt die Szene den Bereich in Unterbereiche auf, bevor das Signal changed() gesendet wird?Antwort
Richtige Antwort: Die Aufteilung in Unterbereiche ermöglicht die Analyse, welche Teile genau geändert wurden, und nur diese neu zu zeichnen. Dies gewährleistet hohe Performance in Echtzeit selbst bei Millionen von Elementen.
Warum ist die Trennung von Daten (QGraphicsScene) und Darstellung (QGraphicsView) ein Architekturvorteil?Antwort
Richtige Antwort: Dies ermöglicht die Anzeige derselben Szene in mehreren verschiedenen View-Widgets, automatisches Neuzeichnen bei Änderungen und effizientere Nutzung von CPU- und Speicherressourcen.
Wie werden Maus- und Tastatur-Events von der View zu einzelnen Szenen-Elementen weitergegeben?Antwort
Richtige Antwort: Die View empfängt Events, konvertiert sie in Szenen-Events mit Szenen-Koordinaten, dann übersetzt die Szene automatisch die Koordinaten in lokale Element-Koordinaten und übergibt das Event an dieses.
Warum bewegen sich beim Verschieben eines Parent-Elements seine Kinder mit?Antwort
Richtige Antwort: Weil jedes Element ein lokales Koordinatensystem relativ zum Parent hat und jede Parent-Transformation automatisch auf alle seine Kinder angewendet wird.
Warum muss die Methode boundingRect() beim Erstellen eines eigenen Elements überschrieben werden?Antwort
Richtige Antwort: Die Methode boundingRect() wird von der View benötigt, um unsichtbare Elemente zu bestimmen, nicht überdeckte Bereiche zum Neuzeichnen zu berechnen und für die korrekte Funktion des Kollisionserkennungs-Mechanismus.
Was ist der grundlegende Unterschied zwischen QGraphicsSimpleTextItem und QGraphicsTextItem?Antwort
Richtige Antwort: QGraphicsSimpleTextItem ist für schnelle Anzeige von einfachem Text mit geringem Speicherverbrauch vorgesehen, während QGraphicsTextItem formatierten Text mit Dokumentbearbeitungs-Möglichkeit unterstützt.
Wie macht man ein Element mit der Maus verschiebbar und welche Methoden werden dabei aufgerufen?Antwort
Richtige Antwort: Man ruft setFlags(QGraphicsItem::ItemIsMovable) auf. Beim Verschieben werden automatisch mousePressEvent(), mouseMoveEvent() und mouseReleaseEvent() aufgerufen, die für zusätzliche Verarbeitung überschrieben werden können.
Wozu dient die Methode collidesWithItem() und welche Kollisionsprüfungsmodi gibt es?Antwort
Richtige Antwort: Die Methode bestimmt Elementkollisionen. Modi: IntersectsItemShape (Formüberschneidung), ContainsItemShape (vollständige Enthaltung), IntersectsItemBoundingRect (schnelle Rechteckprüfung) und ContainsItemBoundingRect.
Warum könnte der Aufruf von setViewport(new QOpenGLWidget) für die View benötigt werden?Antwort
Richtige Antwort: Dies ermöglicht die Nutzung von OpenGL zur Hardware-beschleunigten Szenen-Visualisierung, was die Performance bei komplexer Grafik oder vielen Elementen erheblich steigert.
Warum behalten Widgets, die über QGraphicsProxyWidget in die Szene eingefügt wurden, ihre Funktionalität?Antwort
Richtige Antwort: Dank des Event-Mechanismus empfangen und verarbeiten Widgets weiterhin Benutzeraktionen, während geometrische Transformationen wie bei normalen Szenen-Elementen angewendet werden können.
Welche drei grundlegenden Transformationen bietet die Klasse QTransform und wie werden sie auf Elemente angewendet?Antwort
Richtige Antwort: QTransform bietet translate() (Verschiebung), rotate() (Drehung) und scale() (Skalierung). Transformationen werden auf Elemente durch Aufruf von setTransform() mit einem QTransform-Objekt angewendet.
Was passiert, wenn versucht wird, mehrere QGraphicsScene-Objekte zu erstellen und in einer View anzuzeigen?Antwort
Richtige Antwort: In einer View kann nur eine Szene angezeigt werden — die zuletzt über setScene() gesetzte ersetzt die vorherige. Eine Szene kann jedoch gleichzeitig in mehreren Views angezeigt werden.

Praktische Aufgaben

Einfaches Level

Interaktive Figurengalerie
Erstellen Sie eine Anwendung mit grafischer View, auf der 5 verschiedene geometrische Figuren (Rechteck, Ellipse, Linie, Polygon, Text) platziert sind. Alle Elemente sollen mit der Maus verschiebbar sein und unterschiedliche Füllfarben haben. Fügen Sie Buttons zum Vergrößern und Verkleinern des View-Maßstabs hinzu.
Hinweise: Verwenden Sie die Methoden scene.addRect(), addEllipse(), addLine(), addPolygon(), addText() zur Elementerstellung. Rufen Sie für jedes Element setFlags(QGraphicsItem::ItemIsMovable) auf. Die Methode scale() der View ermöglicht Maßstabsänderung. Vergessen Sie nicht, Farben über QPen und QBrush zu setzen.

Mittleres Level

Kollisionsdetektor mit Visualisierung
Erstellen Sie eine Szene mit zwei Rechtecken verschiedener Farben, die mit der Maus verschoben werden können. Implementieren Sie Kollisionserkennung: Wenn sich die Rechtecke überschneiden, sollen sie ihre Farbe zu Rot ändern, und ohne Überschneidung zu den ursprünglichen Farben zurückkehren. Fügen Sie ein Text-Label hinzu, das den Kollisionsstatus zeigt („Kollision” oder „Keine Kollision”).
Hinweise: Erstellen Sie eine eigene Elementklasse, die von QGraphicsRectItem erbt. Überschreiben Sie mouseMoveEvent() zur Kollisionsprüfung. Verwenden Sie collidesWithItem() zur Überschneidungserkennung. Speichern Sie Zeiger auf beide Elemente für gegenseitige Prüfung. Aktualisieren Sie Farben über setBrush() und Label-Text über setText().

Schwieriges Level

Hierarchisches Sonnensystem mit Animation
Entwickeln Sie ein interaktives Sonnensystemmodell: zentrale Sonne (Kreis), um die 3 Planeten (kleinere Kreise) rotieren. Jeder Planet soll 1-2 Satelliten haben, die um ihn rotieren. Verwenden Sie Parent-Child-Hierarchie zur Elementverknüpfung. Implementieren Sie Rotationsanimation mit QTimer und rotate()-Methoden. Fügen Sie Steuerungs-Widgets hinzu: Schieberegler für Animationsgeschwindigkeit, Pause/Start-Buttons und Reset-Button zur Anfangsposition.
Hinweise: Erstellen Sie die Sonne als Root-Element. Fügen Sie Planeten über setParentItem(sonne) hinzu, Satelliten über setParentItem(planet). Für Rotation verwenden Sie QTimer mit ~16 ms Intervall und rufen Sie im Slot setRotation() mit Inkrement auf. Jedes Element rotiert relativ zu seinem lokalen Koordinatensystem. Fügen Sie Widgets über QGraphicsProxyWidget hinzu. Speichern Sie Anfangspositionen für Reset-Funktion.

💬 Werden Sie Teil der Diskussion!

Haben Sie die grafische Darstellungsarchitektur gemeistert? Fragen zur Arbeit mit QGraphicsScene oder zur Implementierung der Kollisionserkennung?

Teilen Sie Ihre Projekte mit grafischer Darstellung, berichten Sie von Herausforderungen bei der Arbeit mit Transformationen oder helfen Sie anderen, die Elementhierarchie zu verstehen!

Leave a Reply

Your email address will not be published. Required fields are marked *