素材巴巴 > 程序开发 >

Qt实现手势缩放和平移(QGestureEvent)

程序开发 2023-09-12 15:41:31

        最近项目中遇到一个预览图片的需求,同时能够对手势进行处理,可以处理手势的放大、缩小和平移,其中移动可以通过重写鼠标事件实现。而手势事件之前则没有处理过。查阅资料发现Qt自带了一个手势示例,如下图所示,通过阅读代码发现可以通过QGestureEvent事件实现。具体代码如下。

#pragma once#include "ui_testGesture.h"#include 
 #include 
 #include 
 #include 
 #include class testGesture : public QWidget
 {Q_OBJECTpublic:testGesture(QWidget *parent = nullptr);~testGesture();/*** brief:注册所关注的手势事件.* * param gestures:需要关注的事件*/void grabGestures(const QList& gestures);protected:/*** brief:重写paintevent。这是实现的核心,通过修改绘制的中心坐标实现图像根据手势的移动.* * param event*/void paintEvent(QPaintEvent* event)override;/*** brief:尺寸变化.* * param event*/void resizeEvent(QResizeEvent* event)override;/*** brief:双击事件,双击后所有的缩放移动等均失效,恢复到初始状态.* * param event*/void mouseDoubleClickEvent(QMouseEvent* event)override;/*** brief:按下事件,任务需要移动了,不再处理手势.* * param event*/void mousePressEvent(QMouseEvent* event)override;/*** brief:按下并移动的处理.* * param event*/void mouseMoveEvent(QMouseEvent* event)override;/*** brief:.* * param event*/void mouseReleaseEvent(QMouseEvent* event)override;/*** brief:事件过滤处理.* * param event* return */bool event(QEvent* event)override;private:bool gestureEvent(QGestureEvent* event);void panTriggered(QPanGesture* gesture);void pinchTriggered(QPinchGesture* gesture);void swipeTriggered(QSwipeGesture* gesture);private:Ui::testGestureClass ui;qreal m_horizontalOffset{ 0 };    //水平方向偏移量qreal m_verticalOffset{ 0 };      //垂直方向偏移量qreal m_rotationAngle{ 0 };       //旋转角度qreal m_scaleFactor{ 1 };         //缩放比例qreal m_currentStepScaleFactor{ 1 };   //一次手势之后缩放的比例QPoint m_lastPoint{ 0,0 };          //上次点击位置bool m_bIsPressed{ false };         //是否有过点击事件
 };
 

这里最核心的处理便是paintevent的重写和pinchTriggered事件的处理函数。在pinchTriggered处理函数中根据手势的类型,将缩放的比例以及旋转的比例记录下来,结束后则计算此次总的比例并记录在成员变量中。而在paintevent中则调用tanslate函数,依照缩放,旋转值重新计算绘图的位置,从而实现了缩放,旋转。至于panTriggered和swipeTriggered事件因需求中不关注,便未做处理,可根据自身需要进行响应的处理。

#include "testGesture.h"#include 
 #include testGesture::testGesture(QWidget *parent): QWidget(parent)
 {ui.setupUi(this);setFixedSize({ 1920,1080 });grabGestures({});
 }testGesture::~testGesture()
 {}void testGesture::grabGestures(const QList&gestures)
 {QList gesturess;//关注移动,缩放和扫动手势gesturess << Qt::PanGesture;gesturess << Qt::PinchGesture;gesturess << Qt::SwipeGesture;foreach(Qt::GestureType gesture, gesturess)grabGesture(gesture);
 }void testGesture::paintEvent(QPaintEvent* event)
 {QPainter p(this);QPixmap pix("E:/1.jpg");const qreal iw = pix.width();const qreal ih = pix.height();const qreal wh = height();const qreal ww = width();//首先将坐标系移动到整个屏幕的中心p.translate(ww / 2, wh / 2);//然后依据偏移量,再计算出来新的坐标系中心//第二次变换是在上次的基础上进行的计算,也就是translate的所有值是累加的p.translate(m_horizontalOffset, m_verticalOffset);//qDebug() << "qqqq" << m_horizontalOffset << ":" << m_verticalOffset;//p.rotate(m_rotationAngle);//对坐标系进行一个比例放缩p.scale(m_currentStepScaleFactor * m_scaleFactor, m_currentStepScaleFactor * m_scaleFactor);//又进行了一个坐标系中心的变化,减去图片的一半一半,也就是到了图片的左上角//上边计算了偏移量,所以就是移动之后的图片需要绘制的位置,缩放也相应的在上边进行了设置p.translate(-iw / 2, -ih / 2);p.drawPixmap(0, 0, pix);
 }void testGesture::resizeEvent(QResizeEvent* event)
 {update();
 }void testGesture::mouseDoubleClickEvent(QMouseEvent* event)
 {//双击后将双击偏移量,缩放比例,旋转角度都设置为初始值m_rotationAngle = 0;m_scaleFactor = 1;m_currentStepScaleFactor = 1;m_verticalOffset = 0;m_horizontalOffset = 0;update();
 }void testGesture::mousePressEvent(QMouseEvent* event)
 {//鼠标按下后不再处理手势,并记录鼠标按下的位置m_bIsPressed = true;m_lastPoint = event->pos();
 }void testGesture::mouseMoveEvent(QMouseEvent* event)
 {//如果是处理移动事件if (m_bIsPressed){//计算偏移量QPointF mouseDelta = event->pos() - m_lastPoint;m_lastPoint = event->pos();m_horizontalOffset += mouseDelta.x();m_verticalOffset += mouseDelta.y();update();}
 }void testGesture::mouseReleaseEvent(QMouseEvent* event)
 {//不再处理移动m_bIsPressed = false;
 }bool testGesture::event(QEvent* event)
 {//如果是手势,需要给到手势的分派函数if (event->type() == QEvent::Gesture){return gestureEvent(static_cast(event));}return QWidget::event(event);
 }bool testGesture::gestureEvent(QGestureEvent* event)
 {//给到对应的处理事件if (QGesture* swipe = event->gesture(Qt::SwipeGesture))swipeTriggered(static_cast(swipe));else if (QGesture* pan = event->gesture(Qt::PanGesture))panTriggered(static_cast(pan));if (QGesture* pinch = event->gesture(Qt::PinchGesture))pinchTriggered(static_cast(pinch));return true;
 }void testGesture::panTriggered(QPanGesture* gesture)
 {
 #ifndef QT_NO_CURSORswitch (gesture->state()) {case Qt::GestureStarted:case Qt::GestureUpdated:setCursor(Qt::SizeAllCursor);break;default:setCursor(Qt::ArrowCursor);}
 #endifQPointF delta = gesture->delta();//qDebug() << "panTriggered():" << gesture;//m_horizontalOffset += delta.x();//m_verticalOffset += delta.y();update();
 }void testGesture::pinchTriggered(QPinchGesture* gesture)
 {QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();//旋转角度的变化记录if (changeFlags & QPinchGesture::RotationAngleChanged) {qreal rotationDelta = gesture->rotationAngle() - gesture->lastRotationAngle();m_rotationAngle += rotationDelta;qDebug() << "pinchTriggered(): rotate by" <" << m_rotationAngle;}//缩放比例的变化记录if (changeFlags & QPinchGesture::ScaleFactorChanged) {m_currentStepScaleFactor = gesture->totalScaleFactor();qDebug() << "pinchTriggered(): zoom by" <scaleFactor() << "->" << m_currentStepScaleFactor;}//手势结束后将锁防值累乘if (gesture->state() == Qt::GestureFinished) {qDebug() << "finished::" << m_currentStepScaleFactor;m_scaleFactor *= m_currentStepScaleFactor;m_currentStepScaleFactor = 1;}update();
 }void testGesture::swipeTriggered(QSwipeGesture* gesture)
 {if (gesture->state() == Qt::GestureFinished) {if (gesture->horizontalDirection() == QSwipeGesture::Left|| gesture->verticalDirection() == QSwipeGesture::Up) {//qDebug() << "swipeTriggered(): swipe to previous";//goPrevImage();}else {//qDebug() << "swipeTriggered(): swipe to next";//goNextImage();}update();}
 }
 


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。