Kapitel 14. Ereignisse

Kennen Sie die Situation, in der die UI „ihr eigenes Leben führt”: der Button wurde geklickt, aber die Klick-Koordinaten gingen verloren; das Fenster flimmert beim Resize; Drag & Drop verhält sich unvorhersehbar – und es ist unklar, wo genau die Logik „bricht”?

Dieses Kapitel enthüllt, was tatsächlich im Inneren von Qt passiert, wenn „etwas passiert”. Sie werden entdecken, warum Signale und Slots Events nicht ersetzen, und erfahren das Geheimnis, wie professionelle Entwickler präzise Kontrolle über Input (Maus/Tastatur/Touch) erhalten, ohne Chaos im Code und ohne Performance-Verlust.

Es werden accept()/ignore() und die Weitergabekette nach oben in der Hierarchie behandelt, QEvent::type() und das zentrale event(), sowie praktische Fälle mit QMouseEvent, QKeyEvent und QPaintEvent – einschließlich des „Packens” von Redraw-Events, das Ihnen überflüssige paintEvent()-Aufrufe ersparen und die UI spürbar responsiver machen kann.

Schieben Sie nicht auf: Wenn Sie eigene Widgets schreiben oder aufhören möchten, das UI-Verhalten zu „erraten”, ist dieses Kapitel zu überspringen riskant.

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

Selbsttest zum Kapitel

Warum gelten Events als Lower-Level-Mechanismus im Vergleich zu Signalen und Slots?Antwort
Richtige Antwort: Events liefern detaillierte Informationen über Benutzeraktionen (Maus-Koordinaten, Tastencodes), während Signale High-Level-Benachrichtigungen ohne Details sind. Events werden von einer Methode verarbeitet, während Signale mit mehreren Slots verbunden sein können.
Welche Konsequenzen hat der Aufruf der Methode ignore() im Event-Handler und wann kann das nützlich sein?Antwort
Richtige Antwort: Die Methode ignore() gibt das Event an das übergeordnete Objekt zur weiteren Verarbeitung weiter. Dies ist nützlich, wenn das Widget das Event nicht vollständig verarbeiten kann und es an das Eltern-Widget delegieren möchte.
Warum wird mouseMoveEvent() standardmäßig nur bei gedrückter Maustaste aufgerufen?Antwort
Richtige Antwort: Dies ist eine Performance-Optimierung – unnötige Events beim bloßen Bewegen des Cursors werden verhindert. Für das Tracking aller Bewegungen muss setMouseTracking(true) aufgerufen werden.
Was passiert, wenn man Double-Buffering durch Aufruf von setAttribute(Qt::WA_PaintOnScreen) deaktiviert?Antwort
Richtige Antwort: Grafikinformationen verschwinden beim Ändern der Fenstergröße oder bei Überdeckung durch andere Fenster, da ohne Buffering der Inhalt ständig in paintEvent() neu gezeichnet werden muss.
Wozu „packt” Qt eine Serie von QPaintEvent-Events in ein Event?Antwort
Richtige Antwort: Zur Performance-Optimierung – mehrere Redraw-Events werden zu einem mit gemeinsamer Region zusammengefasst, was zu einem einzigen paintEvent()-Aufruf statt mehrfacher führt.
Warum sind Event-Handling-Methoden in Qt als virtual protected definiert?Antwort
Richtige Antwort: Virtual ermöglicht das Überschreiben der Methoden in abgeleiteten Klassen, während protected deren Aufruf nur innerhalb der Klasse und Nachkommen beschränkt, was der Architektur des Qt-Eventsystems entspricht.
In welchen Fällen sollte man die Methode event() anstelle spezialisierter Handler überschreiben?Antwort
Richtige Antwort: Nur zur Verarbeitung von Event-Typen, für die es keine spezialisierten Methoden gibt, oder wenn ein Event vor seiner Verteilung abgefangen werden muss. In allen anderen Fällen sollten spezialisierte Methoden verwendet werden.
Warum erzeugt die Tab-Taste standardmäßig kein keyPressEvent()?Antwort
Richtige Antwort: Die Tab-Taste wird von der event()-Methode zur Fokus-Verwaltung verarbeitet – zur Übergabe des Fokus an das nächste Widget, was ein System-Verhalten der Benutzeroberfläche ist.
Wie verarbeitet man Mausrad-Scrolling korrekt zur Unterstützung verschiedener Geräte (Maus und Touchpad)?Antwort
Richtige Antwort: Es müssen beide Methoden geprüft werden: angleDelta() für Maus mit Scrollrad und pixelDelta() für Touchpad, wobei diejenige verwendet wird, die einen nicht-leeren Wert zurückgibt.
Was passiert, wenn in einer intensiven Schleife processEvents() nicht aufgerufen wird?Antwort
Richtige Antwort: Die grafische Benutzeroberfläche „friert ein” – reagiert nicht mehr auf Benutzeraktionen und wird nicht neu gezeichnet, da die Event-Queue während der Schleifenausführung nicht verarbeitet wird.
Warum wird bei einem Maus-Doppelklick die Methode mousePressEvent() zweimal aufgerufen?Antwort
Richtige Antwort: Ein Doppelklick wird als zwei separate Klicks plus mouseDoubleClickEvent() verarbeitet, damit die Anwendung sowohl auf Einfach- als auch auf Doppelklicks reagieren kann.
Wozu muss das Attribut Qt::WA_AcceptsTouchEvents für Multi-Touch-Verarbeitung gesetzt werden?Antwort
Richtige Antwort: Standardmäßig ignorieren Widgets Multi-Touch-Events und wandeln sie in Maus-Events um. Das Attribut aktiviert den Empfang echter Multi-Touch-Events vom Typ QTouchEvent.
Wie bestimmt man, welcher der 10 Touch-Punkte zu einem bestimmten Finger im Multi-Touch-Interface gehört?Antwort
Richtige Antwort: Mit der Methode TouchPoint::id(), die eine eindeutige ID des Touch-Punkts zurückgibt, die während der gesamten Geste vom Drücken bis zum Loslassen erhalten bleibt.
Warum verwenden die Methoden modifiersInfo() und buttonsInfo() bitweises UND (&) zur Status-Prüfung?Antwort
Richtige Antwort: Der Status von Buttons und Modifiern wird als Bitmaske gespeichert, wobei jedes Bit eine separate Taste repräsentiert. Bitweises UND prüft, ob ein bestimmtes Bit in der Kombination gesetzt ist.
Welchen Wert muss die Methode event() zurückgeben, um die weitere Weitergabe des Events an Eltern zu verhindern?Antwort
Richtige Antwort: Die Methode muss true zurückgeben, was vollständige Verarbeitung des Events bedeutet. Die Rückgabe von false gibt das Event an das Eltern-Widget zur weiteren Verarbeitung weiter.

Praktische Aufgaben

Einfaches Level

Tasteninformations-Widget
Erstellen Sie ein Widget, das Informationen über die gedrückte Taste anzeigt: ihren Code, Unicode-Zeichen (falls vorhanden) und den Status der Modifier-Tasten (Shift, Ctrl, Alt). Beim Drücken einer Taste sollen die Informationen in einem QLabel aktualisiert werden. Implementieren Sie die Verarbeitung sowohl für Tastendruck (keyPressEvent) als auch für Tastenloslassen (keyReleaseEvent) mit unterschiedlichen Hintergrundfarben.
Hinweise: Erben Sie von QLabel. Verwenden Sie die Methoden key(), text() und modifiers() des QKeyEvent-Objekts. Zum Ändern der Hintergrundfarbe verwenden Sie setStyleSheet(). Vergleichen Sie den key()-Wert mit Qt::Key_*-Konstanten.
Mittleres Level

Mausweg-Zeichnung
Entwickeln Sie ein Zeichen-Widget, das sich den Mausweg bei gedrückter linker Maustaste merkt und ihn als Linie anzeigt. Bei Druck der rechten Maustaste soll sich die Linienfarbe ändern. Implementieren Sie Mausbewegungen-Tracking auch ohne gedrückte Tasten, wobei die aktuelle Cursorposition mit einem halbtransparenten Kreis angezeigt wird. Fügen Sie die Möglichkeit hinzu, die Leinwand mit der Escape-Taste zu löschen.
Hinweise: Verwenden Sie QVector<QPoint> zum Speichern der Wegpunkte. Rufen Sie setMouseTracking(true) auf, um alle Bewegungen zu tracken. Zeichnen Sie in paintEvent() Linien durch die gespeicherten Punkte. Verarbeiten Sie die Events mousePressEvent, mouseMoveEvent und keyPressEvent.
Schwieriges Level

Multi-Touch-Leinwand mit Gesten
Erstellen Sie eine fortgeschrittene Zeichen-Leinwand mit Multi-Touch-Gesten-Unterstützung: Zeichnen mit mehreren Fingern gleichzeitig (jeder Finger zeichnet eine Linie in seiner eigenen Farbe), Pinch-to-Zoom-Geste mit zwei Fingern zum Ändern der Pinselstärke, Rotationsgeste mit zwei Fingern zum Drehen der Leinwand. Implementieren Sie Indikation aktiver Touch-Punkte und Anzeige der aktuellen Pinselstärke. Fügen Sie einen Button zum Zurücksetzen von Zoom und Rotation hinzu.
Hinweise: Aktivieren Sie setAttribute(Qt::WA_AcceptsTouchEvents). Verarbeiten Sie in event() QEvent::TouchBegin/Update/End. Verwenden Sie QMap<int, QVector<QPointF>> zum Speichern der Pfade jedes Fingers nach id(). Für Zoom berechnen Sie den Abstand zwischen zwei Punkten. Für Rotation verwenden Sie QLineF::angleTo(). Wenden Sie QTransform für Transformationen beim Zeichnen an.

💬 Beteiligen Sie sich an der Diskussion!

Haben Sie Tastatur- und Maus-Events verstanden? Fragen zum Unterschied zwischen Events und Signalen?

Auf Probleme bei der Verarbeitung von Multi-Touch-Gesten gestoßen oder unsicher, wann man event() und wann spezialisierte Handler verwenden soll?

Teilen Sie Ihre Erfahrung bei der Implementierung eigener Events, stellen Sie Fragen zur Performance oder helfen Sie anderen Lesern, das Qt-Eventmodell zu meistern!

Leave a Reply

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