Ejemplo de gestos con imágenes
Demuestra el uso de gestos sencillos en un widget.
Este ejemplo muestra cómo habilitar gestos para un widget y utilizar la entrada gestual para realizar acciones.

Utilizamos dos clases para crear la interfaz de usuario de la aplicación: MainWidget y ImageWidget. La clase MainWidget se utiliza simplemente como un contenedor para la clase ImageWidget, que configuraremos para aceptar la entrada de gestos. Dado que estamos interesados en la forma en que se utilizan los gestos, nos concentraremos en la implementación de la clase ImageWidget.
Definición de la clase ImageWidget
La clase ImageWidget es una simple subclase de QWidget que reimplementa la función manejadora general QWidget::event() además de varios manejadores de eventos más específicos:
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*); ... };
También implementamos una función de ayuda privada, gestureEvent(), para ayudar a gestionar los eventos de gestos enviados al widget, y tres funciones para realizar acciones basadas en gestos: panTriggered() pinchTriggered() y swipeTriggered().
Implementación de la clase ImageWidget
En el constructor del widget, comenzamos configurando varios parámetros que se utilizarán para controlar la forma en que se muestran las imágenes.
ImageWidget::ImageWidget(QWidget *parent) : QWidget(parent), position(0), horizontalOffset(0), verticalOffset(0) , rotationAngle(0), scaleFactor(1), currentStepScaleFactor(1) { setMinimumSize(QSize(100, 100)); }
Habilitamos tres de los gestos estándar para el widget llamando a QWidget::grabGesture() con los tipos de gestos que necesitamos. Estos serán reconocidos por el reconocedor de gestos por defecto de la aplicación, y los eventos serán enviados a nuestro widget.
Dado que QWidget no define un manejador de eventos específico para gestos, el widget necesita reimplementar el manejador general QWidget::event() para recibir eventos de gestos.
bool ImageWidget::event(QEvent *event) { if (event->type() == QEvent::Gesture) return gestureEvent(static_cast<QGestureEvent*>(event)); return QWidget::event(event); }
Implementamos el manejador de eventos para delegar los eventos de gestos a una función privada escrita específicamente para la tarea, y pasamos todos los demás eventos a la implementación de QWidget.
La función gestureHandler() examina los gestos suministrados por el recién entregado QGestureEvent. Dado que sólo se puede utilizar un gesto de un tipo determinado en un widget en un momento dado, podemos comprobar cada tipo de gesto utilizando la función QGestureEvent::gesture():
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; }
Si se suministra un objeto QGesture para un determinado tipo de gesto, llamamos a una función de propósito especial para que se ocupe de él, casteando el objeto de gesto a la subclase QGesture apropiada.
Para ilustrar cómo una aplicación puede interpretar un gesto estándar, mostramos la implementación de la función pinchTriggered(), que gestiona el gesto de pellizcar cuando el usuario mueve dos dedos sobre la pantalla o el dispositivo de entrada:
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(); }
La clase QPinchGesture proporciona propiedades para interpretar la distancia cambiante entre los dos puntos táctiles como un factor de zoom, y el ángulo delta como una rotación a aplicar a la imagen. El punto central entre los puntos táctiles podría utilizarse para arrastrar la imagen, pero en este ejemplo utilizamos el gesto de panorámica para ese fin.
scaleFactor() es un valor relativo que representa cuánto debe cambiar el zoom de un evento al siguiente, mientras que totalScaleFactor() proporciona la cantidad de zoom que se ha expresado desde que comenzó el gesto. Cuando se suelten los puntos táctiles y comience otro gesto, totalScaleFactor() comenzará de nuevo en 1.0. En este caso almacenamos totalScaleFactor() en la variable currentStepScaleFactor para que pueda ser utilizada en paintEvent() para escalar la imagen. Alternativamente sería posible simplemente multiplicar el factor de escala total almacenado por scaleFactor() aquí en el manejador de pellizco.
Por el contrario, rotationAngle() representa la cantidad de rotación desde que comenzó el gesto de pellizcar, mientras que lastRotationAngle() proporciona el valor anterior. Por tanto, es necesario restar para obtener un delta incremental. Cuando el usuario inicia un nuevo gesto de pellizco, rotationAngle() partirá de cero, y queremos que la imagen comience a girar desde su ángulo actual. Esto se consigue sumando el delta al almacenado en rotationAngle (que se aplicará en paintEvent()). Si simplemente asignáramos totalRotationAngle() al almacenado rotationAngle, un nuevo gesto haría que la imagen se restableciera a una orientación derecha-arriba antes de empezar a rotar de nuevo. Pero sería posible almacenar el ángulo de rotación desde que comenzó el gesto y añadirlo a rotationAngle en paintEvent(), del mismo modo que almacenamos la cantidad de zoom desde que comenzó el gesto.
Los gestos de paneo y deslizamiento en este ejemplo también se manejan en funciones separadas, y utilizan los valores de las propiedades de los objetos QGesture que se les pasan.
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); }
En paintEvent(), scaleFactor representa el nivel de zoom antes de que comenzara el gesto de pellizco, mientras que currentStepScaleFactor representa el factor de zoom adicional mientras se está realizando un gesto de pellizco. Pero para la rotación, sólo se almacena el rotationAngle actual. Los desplazamientos horizontal y vertical representan la distancia que la imagen ha sido arrastrada por el gesto de panorámica.
© 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.