Gesten in Widgets und Grafikansicht

Qt enthält ein Framework für die Gestenprogrammierung, das in der Lage ist, Gesten aus einer Reihe von Ereignissen zu bilden, unabhängig von den verwendeten Eingabemethoden. Eine Geste kann eine bestimmte Mausbewegung, eine Touchscreen-Aktion oder eine Reihe von Ereignissen aus einer anderen Quelle sein. Die Art der Eingabe, die Interpretation der Geste und die durchgeführte Aktion liegen im Ermessen des Entwicklers.

Überblick

QGesture ist die zentrale Klasse im Gesten-Framework von Qt, die einen Container für Informationen über die vom Benutzer ausgeführten Gesten bereitstellt. QGesture stellt Eigenschaften zur Verfügung, die allgemeine Informationen liefern, die für alle Gesten gelten, und diese können erweitert werden, um zusätzliche gestenspezifische Informationen bereitzustellen. Gängige Schwenk-, Kneif- und Wischgesten werden durch spezielle Klassen dargestellt: QPanGesture, QPinchGesture und QSwipeGesture.

Entwickler können auch neue Gesten implementieren, indem sie die Klasse QGestureRecognizer unterklassifizieren und erweitern. Das Hinzufügen von Unterstützung für eine neue Geste beinhaltet die Implementierung von Code zur Erkennung der Geste anhand von Eingabeereignissen. Dies wird im Abschnitt Erstellen eines eigenen Gestenerkenners beschrieben.

Verwenden von Standardgesten mit Widgets

Gesten können für Instanzen der Unterklassen QWidget und QGraphicsObject aktiviert werden. Ein Objekt, das Gesteneingaben akzeptiert, wird in dieser Dokumentation als Zielobjekt bezeichnet.

Um eine Geste für ein Zielobjekt zu aktivieren, rufen Sie dessen Funktion QWidget::grabGesture() oder QGraphicsObject::grabGesture() mit einem Argument auf, das den gewünschten Gesten-Typ beschreibt. Die Standardtypen werden durch das Qt::GestureType enum definiert und umfassen viele häufig verwendete Gesten.

for (Qt::GestureType gesture : gestures)
    grabGesture(gesture);

Im obigen Code werden die Gesten im Konstruktor des Zielobjekts selbst eingerichtet.

Behandlung von Ereignissen

Wenn der Benutzer eine Geste ausführt, werden QGestureEvent -Ereignisse an das Zielobjekt übermittelt, die durch Neuimplementierung der Handler-Funktion QWidget::event() für Widgets oder QGraphicsItem::sceneEvent() für Grafikobjekte behandelt werden können.

Da ein Zielobjekt mehr als einen Gesten-Typ abonnieren kann, kann QGestureEvent mehr als eine QGesture enthalten, die anzeigt, dass mehrere mögliche Gesten gleichzeitig aktiv sind. Es ist dann Sache des Widgets, zu bestimmen, wie mit diesen mehreren Gesten umgegangen werden soll, und zu entscheiden, ob einige zu Gunsten anderer abgebrochen werden sollen.

Jede QGesture, die in einem QGestureEvent Objekt enthalten ist, kann einzeln oder alle zusammen akzeptiert() oder ignoriert() werden. Außerdem können Sie die einzelnen QGesture Datenobjekte (den Zustand) mit Hilfe mehrerer Getter abfragen.

Standardverfahren für die Ereignisbehandlung

Ein QGesture wird standardmäßig akzeptiert, wenn es in Ihrem Widget eintrifft. Es ist jedoch gute Praxis, eine Geste immer explizit anzunehmen oder abzulehnen. Die allgemeine Regel lautet: Wenn Sie eine Geste akzeptieren, verwenden Sie sie. Wenn Sie sie ignorieren, sind Sie nicht an ihr interessiert. Das Ignorieren einer Geste kann bedeuten, dass sie einem anderen Zielobjekt angeboten wird, oder sie wird abgebrochen.

Jedes QGesture hat mehrere Zustände, die es durchläuft; es gibt eine genau definierte Art und Weise, den Zustand zu ändern, typischerweise ist die Benutzereingabe die Ursache für Zustandsänderungen (z.B. durch Starten und Stoppen der Interaktion), aber auch das Widget kann Zustandsänderungen verursachen.

Wenn ein bestimmtes QGesture zum ersten Mal an ein Widget oder Grafikelement übergeben wird, befindet es sich im Zustand Qt::GestureStarted. Die Art und Weise, wie Sie die Geste zu diesem Zeitpunkt behandeln, beeinflusst, ob Sie später mit ihr interagieren können.

  • Das Akzeptieren der Geste bedeutet, dass das Widget auf die Geste reagiert und es werden Gesten mit dem Qt::GestureUpdatedstate folgen.
  • Das Ignorieren der Geste bedeutet, dass Ihnen die Geste nie wieder angeboten wird. Sie wird auch einem übergeordneten Widget oder Element angeboten.
  • Der Aufruf von setGestureCancelPolicy() für die Geste, wenn sie sich in ihrem Startzustand befindet und auch akzeptiert wird, kann dazu führen, dass andere Gesten abgebrochen werden.

Die Verwendung von QGesture::CancelAllInContext zum Abbrechen einer Geste führt dazu, dass alle Gesten, egal in welchem Zustand, abgebrochen werden, sofern sie nicht explizit akzeptiert werden. Dies bedeutet, dass aktive Gesten für Kinder abgebrochen werden. Es bedeutet auch, dass Gesten, die im selben QGestureEvent geliefert werden, abgebrochen werden, wenn das Widget sie ignoriert. Dies kann ein nützlicher Weg sein, um alle Gesten herauszufiltern, außer derjenigen, an der Sie interessiert sind.

Beispiel für Ereignisbehandlung

Der Einfachheit halber implementiert das Image Gestures-Beispiel die allgemeine event()-Handlerfunktion neu und delegiert Gestenereignisse an eine spezielle gestureEvent()-Funktion:

bool ImageWidget::event(QEvent *event)
{
    if (event->type() == QEvent::Gesture)
        return gestureEvent(static_cast<QGestureEvent*>(event));
    return QWidget::event(event);
}

Die an das Zielobjekt gelieferten Gestenereignisse können einzeln untersucht und entsprechend behandelt werden:

bool ImageWidget::gestureEvent(QGestureEvent *event)
{
    qCDebug(lcExample) << "gestureEvent():" << event;
    if (QGesture *swipe = event->gesture(Qt::SwipeGesture))
        swipeTriggered(static_cast<QSwipeGesture *>(swipe));
    else if (QGesture *pan = event->gesture(Qt::PanGesture))
        panTriggered(static_cast<QPanGesture *>(pan));
    if (QGesture *pinch = event->gesture(Qt::PinchGesture))
        pinchTriggered(static_cast<QPinchGesture *>(pinch));
    return true;
}

Die Reaktion auf eine Geste besteht einfach darin, das QGesture Objekt, das in der an das Zielobjekt gesendeten QGestureEvent geliefert wird, zu erhalten und die darin enthaltenen Informationen zu untersuchen.

void ImageWidget::swipeTriggered(QSwipeGesture *gesture)
{
    if (gesture->state() == Qt::GestureFinished) {
        if (gesture->horizontalDirection() == QSwipeGesture::Left
            || gesture->verticalDirection() == QSwipeGesture::Up) {
            qCDebug(lcExample) << "swipeTriggered(): swipe to previous";
            goPrevImage();
        } else {
            qCDebug(lcExample) << "swipeTriggered(): swipe to next";
            goNextImage();
        }
        update();
    }
}

Hier untersuchen wir die Richtung, in die der Benutzer das Widget gestrichen hat, und ändern den Inhalt entsprechend.

Erstellen eines eigenen Gestenerkenners

Das Hinzufügen von Unterstützung für eine neue Geste beinhaltet das Erstellen und Registrieren eines neuen Gestenerkenners. Je nach dem Erkennungsprozess für die Geste kann es auch erforderlich sein, ein neues Gestenobjekt zu erstellen.

Um einen neuen Gestenerkenner zu erstellen, müssen Sie die Unterklasse QGestureRecognizer verwenden, um eine benutzerdefinierte Erkennerklasse zu erstellen. Es gibt eine virtuelle Funktion, die Sie neu implementieren müssen, und zwei weitere, die je nach Bedarf neu implementiert werden können.

Filtern von Eingabeereignissen

Die Funktion recognize() muss neu implementiert werden. Diese Funktion verarbeitet und filtert die eingehenden Eingabeereignisse für die Zielobjekte und stellt fest, ob sie der Geste entsprechen, nach der der Erkenner sucht oder nicht.

Obwohl die Logik für die Gestenerkennung in dieser Funktion implementiert ist, möglicherweise unter Verwendung eines Zustandsautomaten, der auf den Qt::GestureState enums basiert, können Sie dauerhafte Informationen über den Zustand des Erkennungsprozesses in dem mitgelieferten QGesture Objekt speichern.

Ihre Funktion recognize() muss einen Wert von QGestureRecognizer::Result zurückgeben, der den Zustand der Erkennung für eine bestimmte Geste und ein bestimmtes Zielobjekt angibt. Dies bestimmt, ob ein Gestenereignis an ein Zielobjekt übermittelt wird oder nicht.

Benutzerdefinierte Gesten

Wenn Sie sich dafür entscheiden, eine Geste durch eine benutzerdefinierte QGesture Unterklasse darzustellen, müssen Sie die Funktion create() neu implementieren, um Instanzen Ihrer Gestenklasse anstelle der Standardinstanzen von QGesture zu erstellen. Alternativ können Sie auch die Standardinstanzen von QGesture verwenden, ihnen aber zusätzliche dynamische Eigenschaften hinzufügen, um spezifische Details der Geste auszudrücken, die Sie behandeln möchten.

Gesten zurücksetzen

Wenn Sie benutzerdefinierte Gestenobjekte verwenden, die zurückgesetzt oder anderweitig speziell behandelt werden müssen, wenn eine Geste abgebrochen wird, müssen Sie die Funktion reset() neu implementieren, um diese speziellen Aufgaben durchzuführen.

Beachten Sie, dass die QGesture Objekte nur einmal für jede Kombination von Zielobjekt und Gestenart erstellt werden, und dass sie möglicherweise jedes Mal wieder verwendet werden, wenn der Benutzer versucht, dieselbe Gestenart auf dem Zielobjekt auszuführen. Daher kann es sinnvoll sein, die Funktion reset() neu zu implementieren, um nach jedem vorherigen Versuch, eine Geste zu erkennen, aufzuräumen.

Verwendung eines neuen Gestenerkenners

Um einen Gestenerkenner zu verwenden, erstellen Sie eine Instanz Ihrer QGestureRecognizer Unterklasse und registrieren Sie sie mit QGestureRecognizer::registerRecognizer() in der Anwendung. Ein Erkenner für einen bestimmten Gesten-Typ kann mit QGestureRecognizer::unregisterRecognizer() wieder entfernt werden.

Weitere Lektüre

Das Beispiel für Bildgesten zeigt, wie man Gesten für ein Widget in einer einfachen Bildbetrachtungsanwendung aktiviert.

Gesten in Qt Quick

Qt Quick verfügt nicht über einen generischen globalen Gestenerkenner; stattdessen können einzelne Komponenten auf ihre eigene Weise auf Berührungsereignisse reagieren. Zum Beispiel behandelt PinchArea Zwei-Finger-Gesten, Flickable ist für das Streichen von Inhalten mit einem einzelnen Finger, und MultiPointTouchArea kann eine beliebige Anzahl von Berührungspunkten behandeln und dem Anwendungsentwickler erlauben, benutzerdefinierten Code zur Gestenerkennung zu schreiben.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.