Auf dieser Seite

Beispiel für Bildgesten

Veranschaulicht die Verwendung einfacher Gesten in einem Widget.

Dieses Beispiel zeigt, wie man Gesten für ein Widget aktiviert und Gesteneingaben nutzt, um Aktionen auszuführen.

Gesten-Eingaben auf dem Bild einer Blume

Wir verwenden zwei Klassen, um die Benutzeroberfläche für die Anwendung zu erstellen: „ MainWidget “ und „ ImageWidget “. Die Klasse „ MainWidget “ dient lediglich als Container für die Klasse „ ImageWidget “, die wir so konfigurieren werden, dass sie Gesteneingaben akzeptiert. Da wir uns für die Art und Weise interessieren, wie Gesten verwendet werden, konzentrieren wir uns auf die Implementierung der Klasse „ ImageWidget “.

Definition der Klasse „ImageWidget“

Die Klasse „ ImageWidget “ ist eine einfache Unterklasse von „ QWidget “, die neben der allgemeinen Handler-Funktion „ QWidget::event()“ mehrere spezifischere Ereignis-Handler neu implementiert:

class ImageWidget : public QWidget
{
    Q_OBJECT

public:
    ImageWidget(QWidget *parent = nullptr);
    void openDirectory(const QString &url);
    void grabGestures(const QList<Qt::GestureType> &gestures);

protected:
    bool event(QEvent *event) override;
    void paintEvent(QPaintEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;
    void mouseDoubleClickEvent(QMouseEvent *event) override;

private:
    bool gestureEvent(QGestureEvent *event);
    void panTriggered(QPanGesture*);
    void pinchTriggered(QPinchGesture*);
    void swipeTriggered(QSwipeGesture*);
    ...
};

Außerdem implementieren wir eine private Hilfsfunktion, ` gestureEvent()`, zur Verwaltung der an das Widget übermittelten Gestenereignisse sowie drei Funktionen zur Ausführung von Aktionen auf Basis von Gesten: ` panTriggered()`, ` pinchTriggered() ` und ` swipeTriggered()`.

Implementierung der Klasse „ImageWidget“

Im Konstruktor des Widgets richten wir zunächst verschiedene Parameter ein, mit denen die Darstellung der Bilder gesteuert wird.

ImageWidget::ImageWidget(QWidget *parent)
    : QWidget(parent), position(0), horizontalOffset(0), verticalOffset(0)
    , rotationAngle(0), scaleFactor(1), currentStepScaleFactor(1)
{
    setMinimumSize(QSize(100, 100));
}

Wir aktivieren drei der Standardgesten für das Widget, indem wir ` QWidget::grabGesture()` mit den gewünschten Gestentypen aufrufen. Diese werden vom standardmäßigen Gestenerkennungsmodul der Anwendung erkannt, und die Ereignisse werden an unser Widget weitergeleitet.

Da ` QWidget ` keinen spezifischen Ereignisbehandler für Gesten definiert, muss das Widget die allgemeine Methode ` QWidget::event()` neu implementieren, um Gestenereignisse zu empfangen.

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

Wir implementieren den Ereignis-Handler so, dass er Gestenereignisse an eine eigens für diese Aufgabe geschriebene private Funktion delegiert und alle anderen Ereignisse an die Implementierung von ` QWidget` weiterleitet.

Die Funktion ` gestureHandler() ` untersucht die Gesten, die von dem neu übergebenen ` QGestureEvent` bereitgestellt werden. Da zu einem bestimmten Zeitpunkt nur eine Geste eines bestimmten Typs auf einem Widget verwendet werden kann, können wir mithilfe der Funktion ` QGestureEvent::gesture()` für jeden Gestentyp prüfen:

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;
}

Wird für einen bestimmten Gestentyp ein ` QGesture `-Objekt übergeben, rufen wir eine spezielle Funktion auf, um diese zu verarbeiten, wobei wir das Gestenobjekt in die entsprechende Unterklasse von ` QGesture ` umwandeln.

Um zu veranschaulichen, wie eine Standardgeste von einer Anwendung interpretiert werden kann, zeigen wir die Implementierung der Funktion ` pinchTriggered() `, die die Pinch-Geste verarbeitet, wenn der Benutzer zwei Finger auf dem Display oder dem Eingabegerät bewegt:

void ImageWidget::pinchTriggered(QPinchGesture *gesture)
{
    QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
    if (changeFlags & QPinchGesture::RotationAngleChanged) {
        qreal rotationDelta = gesture->rotationAngle() - gesture->lastRotationAngle();
        rotationAngle += rotationDelta;
        qCDebug(lcExample) << "pinchTriggered(): rotate by" <<
            rotationDelta << "->" << rotationAngle;
    }
    if (changeFlags & QPinchGesture::ScaleFactorChanged) {
        currentStepScaleFactor = gesture->totalScaleFactor();
        qCDebug(lcExample) << "pinchTriggered(): zoom by" <<
            gesture->scaleFactor() << "->" << currentStepScaleFactor;
    }
    if (gesture->state() == Qt::GestureFinished) {
        scaleFactor *= currentStepScaleFactor;
        currentStepScaleFactor = 1;
    }
    update();
}

Die Klasse „ QPinchGesture “ stellt Eigenschaften bereit, um den sich ändernden Abstand zwischen den beiden Berührungspunkten als Zoomfaktor und das Winkel-Delta als auf das Bild anzuwendende Drehung zu interpretieren. Der Mittelpunkt zwischen den Berührungspunkten könnte zum Verschieben des Bildes verwendet werden, doch in diesem Beispiel nutzen wir hierfür die Schwenkgeste.

„ scaleFactor() “ ist ein relativer Wert, der angibt, um wie viel sich der Zoom von einem Ereignis zum nächsten ändern soll, während „ totalScaleFactor() “ den seit Beginn der Geste ausgeprägten Zoomwert angibt. Wenn die Berührungspunkte losgelassen werden und eine neue Geste beginnt, wird „ totalScaleFactor() “ wieder bei 1,0 gesetzt. In diesem Fall speichern wir „ totalScaleFactor() “ in der Variablen „ currentStepScaleFactor “, damit es in „ paintEvent() “ zum Skalieren des Bildes verwendet werden kann. Alternativ wäre es möglich, den gespeicherten Gesamt-Skalierungsfaktor hier im Pinch-Handler einfach mit „ scaleFactor() “ zu multiplizieren.

Im Gegensatz dazu stellt rotationAngle() den Drehwinkel seit Beginn der Pinch-Geste dar, während lastRotationAngle() den vorherigen Wert liefert. Daher ist eine Subtraktion erforderlich, um ein inkrementelles Delta zu erhalten. Wenn der Benutzer eine neue Pinch-Geste beginnt, startet „ rotationAngle() “ bei Null, und wir möchten, dass sich das Bild ab seinem aktuellen Winkel zu drehen beginnt. Dies wird erreicht, indem das Delta zum gespeicherten „ rotationAngle “ addiert wird (das in „ paintEvent() “ angewendet wird). Würden wir einfach ` totalRotationAngle() ` dem gespeicherten ` rotationAngle` zuweisen, würde eine neue Geste dazu führen, dass das Bild auf eine aufrechte Ausrichtung zurückgesetzt wird, bevor es sich erneut dreht. Es wäre jedoch möglich, den Drehwinkel seit Beginn der Geste zu speichern und ihn in ` paintEvent()` zu ` rotationAngle ` hinzuzufügen – genau wie wir den Zoomwert seit Beginn der Geste speichern.

Die Schwenk- und Wischgesten in diesem Beispiel werden ebenfalls in separaten Funktionen verarbeitet und verwenden die Werte der Eigenschaften der an sie übergebenen „ QGesture “-Objekte.

void ImageWidget::paintEvent(QPaintEvent*)
{
    QPainter p(this);

    if (files.isEmpty() && !path.isEmpty()) {
        p.drawText(rect(), Qt::AlignCenter|Qt::TextWordWrap,
                         tr("No supported image formats found"));
        return;
    }

    const qreal iw = currentImage.width();
    const qreal ih = currentImage.height();
    const qreal wh = height();
    const qreal ww = width();

    p.translate(ww / 2, wh / 2);
    p.translate(horizontalOffset, verticalOffset);
    p.rotate(rotationAngle);
    p.scale(currentStepScaleFactor * scaleFactor, currentStepScaleFactor * scaleFactor);
    p.translate(-iw / 2, -ih / 2);
    p.drawImage(0, 0, currentImage);
}

In „ paintEvent() “ stellt „scaleFactor“ den Zoomfaktor vor Beginn der Pinch-Geste dar, während „currentStepScaleFactor“ den zusätzlichen Zoomfaktor während einer laufenden Pinch-Geste angibt. Bei der Drehung wird jedoch nur der aktuelle „rotationAngle“ gespeichert. Die horizontalen und vertikalen Offsets geben den Abstand an, um den das Bild durch die Schwenkgeste verschoben wurde.

Beispielprojekt auf code.qt.io

© 2026 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.