Beispiel für Bildgesten
Demonstriert die Verwendung von einfachen Gesten in einem Widget.
Dieses Beispiel zeigt, wie man Gesten für ein Widget aktiviert und die Gesteneingabe zur Durchführung von Aktionen verwendet.
Wir verwenden zwei Klassen, um die Benutzeroberfläche für die Anwendung zu erstellen: MainWidget
und ImageWidget
. Die Klasse MainWidget
wird einfach als Container für die Klasse ImageWidget
verwendet, die wir so konfigurieren werden, dass sie Gesteneingaben akzeptiert. Da wir an der Art und Weise interessiert sind, wie Gesten verwendet werden, konzentrieren wir uns auf die Implementierung der Klasse ImageWidget
.
Definition der ImageWidget-Klasse
Die Klasse ImageWidget
ist eine einfache Unterklasse von QWidget, die die allgemeine Handler-Funktion QWidget::event() sowie mehrere spezifischere Event-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*); ... };
Wir implementieren auch eine private Hilfsfunktion, gestureEvent()
, um die Verwaltung von Gestenereignissen, die an das Widget geliefert werden, zu unterstützen, und drei Funktionen, um Aktionen auf der Grundlage von Gesten durchzuführen: panTriggered()
, pinchTriggered()
und swipeTriggered()
.
Implementierung der ImageWidget-Klasse
Im Konstruktor des Widgets werden zunächst verschiedene Parameter festgelegt, die zur Steuerung der Bilddarstellung verwendet werden.
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 benötigten Gestenarten aufrufen. Diese werden von der standardmäßigen Gestenerkennung der Anwendung erkannt, und Ereignisse werden an unser Widget geliefert.
Da QWidget keinen spezifischen Ereignishandler für Gesten definiert, muss das Widget den allgemeinen 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 Ereignishandler, um Gestenereignisse an eine private Funktion zu delegieren, die speziell für diese Aufgabe geschrieben wurde, und übergeben alle anderen Ereignisse an die Implementierung von QWidget.
Die Funktion gestureHandler()
prüft die Gesten, die von der neu gelieferten QGestureEvent geliefert werden. Da immer nur eine Geste eines bestimmten Typs auf einem Widget verwendet werden kann, können wir jeden Gesten-Typ mit der Funktion QGestureEvent::gesture() überprü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; }
Wenn ein QGesture Objekt für einen bestimmten Gesten-Typ geliefert wird, rufen wir eine spezielle Funktion auf, um damit umzugehen, indem wir das Gesten-Objekt in die entsprechende QGesture Unterklasse 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 Bildschirm oder 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 zur Verfügung, die den sich ändernden Abstand zwischen den beiden Berührungspunkten als Zoomfaktor und den Winkel delta als auf das Bild anzuwendende Drehung interpretieren. Der Mittelpunkt zwischen den Berührungspunkten könnte zum Ziehen des Bildes verwendet werden, aber in diesem Beispiel verwenden wir die Schwenkgeste für diesen Zweck.
scaleFactor()
ist ein relativer Wert, der angibt, wie stark sich der Zoom von einem Ereignis zum nächsten ändern soll, während totalScaleFactor()
den Umfang des Zooms angibt, der seit Beginn der Geste ausgedrückt wurde. Wenn die Berührungspunkte losgelassen werden und eine weitere Geste beginnt, beginnt totalScaleFactor()
wieder bei 1,0. In diesem Fall wird totalScaleFactor()
in der Variablen currentStepScaleFactor
gespeichert, damit sie in paintEvent()
zur Skalierung des Bildes verwendet werden kann. Alternativ wäre es möglich, den gespeicherten Gesamtskalierungsfaktor hier im Pinch-Handler einfach mit scaleFactor()
zu multiplizieren.
Im Gegensatz dazu stellt rotationAngle()
den Betrag der Drehung seit Beginn der Pinch-Geste dar, während lastRotationAngle()
den vorherigen Wert liefert. Es muss also subtrahiert werden, um ein inkrementelles Delta zu erhalten. Wenn der Benutzer eine neue Pinch-Geste beginnt, startet rotationAngle()
bei Null, und wir wollen, dass das Bild ab dem aktuellen Winkel zu rotieren beginnt. Dies wird erreicht, indem das Delta zu dem gespeicherten rotationAngle
addiert wird (das in paintEvent()
angewendet wird). Wenn wir totalRotationAngle()
einfach der gespeicherten rotationAngle
zuweisen würden, würde eine neue Geste dazu führen, dass das Bild auf die rechte Seite zurückgesetzt wird, bevor es wieder zu rotieren beginnt. Es wäre jedoch möglich, den Drehwinkel seit Beginn der Geste zu speichern und ihn in paintEvent()
zu rotationAngle
hinzuzufügen, so wie wir auch den Umfang des Zooms seit Beginn der Geste speichern.
Die Schwenk- und Wischgesten in diesem Beispiel werden ebenfalls in separaten Funktionen behandelt und verwenden die Werte von Eigenschaften der QGesture Objekte, die an sie übergeben werden.
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()
steht scaleFactor für die Zoomstufe vor Beginn der Pinch-Geste, während currentStepScaleFactor für den zusätzlichen Zoomfaktor während einer Pinch-Geste steht. Für die Rotation wird jedoch nur der aktuelle Rotationswinkel gespeichert. Die horizontalen und vertikalen Offsets stellen die Distanz dar, um die das Bild durch die Pan-Geste verschoben wurde.
© 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.