由于项目要求,需要在QWidget中实现一个手势操作的功能,对图片进行放大/缩小/平移功能,并且还需要支持通过鼠标和键盘来实现该功能。其实这种功能在QGraphicsView中实现比较简单, 不过在QWidget中也能实现,本次通过QGestureEvent来捕捉手势操作,然后对图片进行缩放或者移动。

废话不多说,直接上代码

首先来看头文件:

class QGestureEvent;
class QPanGesture;
class QPinchGesture;
class QSwipeGesture;
class CProjectionPicture;class CProjectionPicture : public QWidget
{Q_OBJECT
public:CProjectionPicture(QWidget *parent = 0);void setPicture(QImage & image);protected:// 放大/缩小void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;// 平移void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;bool event(QEvent *event) Q_DECL_OVERRIDE;void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;public Q_SLOTS:void zoomIn();  // 放大void zoomOut();  // 缩小void zoom(float scale); // 缩放 - scaleFactor:缩放的比例因子void translate(QPointF delta);  // 平移private:bool gestureEvent(QGestureEvent *event);void panTriggered(QPanGesture*);void pinchTriggered(QPinchGesture*);QImage loadImage(const QString &fileName);QImage currentImage;qreal horizontalOffset;qreal verticalOffset;qreal scaleFactor;qreal currentStepScaleFactor;Qt::MouseButton m_translateButton;  // 平移按钮bool m_bMouseTranslate;qreal m_zoomDelta;  // 缩放的增量QPoint m_lastMousePos;  // 鼠标最后按下的位置};

源文件:

CProjectionPicture::CProjectionPicture(QWidget *parent): QWidget(parent),horizontalOffset(0),verticalOffset(0),scaleFactor(1),currentStepScaleFactor(1),m_translateButton(Qt::LeftButton),m_bMouseTranslate(false),m_zoomDelta(0.2),
{this->setFocusPolicy(Qt::ClickFocus);grabGesture(Qt::PanGesture);grabGesture(Qt::PinchGesture);grabGesture(Qt::SwipeGesture);
}
void CProjectionPicture::setPicture(QImage &image)
{currentImage = image.convertToFormat(QImage::Format_RGB888);update();
}bool CProjectionPicture::event(QEvent *event)
{if (event->type() == QEvent::Gesture)return gestureEvent(static_cast<QGestureEvent*>(event));return QWidget::event(event);
}void CProjectionPicture::paintEvent(QPaintEvent*)
{QPainter painter(this);QImage image = currentImage;if(!image.isNull()){image = image.scaled(this->width()*currentStepScaleFactor * scaleFactor,this->height()*currentStepScaleFactor * scaleFactor,Qt::KeepAspectRatio,Qt::SmoothTransformation);}const qreal iw = image.width();const qreal ih = image.height();const qreal wh = height();const qreal ww = width();painter.translate(ww/2, wh/2);painter.translate(horizontalOffset, verticalOffset);//painter.scale(currentStepScaleFactor * scaleFactor, currentStepScaleFactor * scaleFactor);painter.translate(-iw/2, -ih/2);painter.drawImage(0,0,image);}void CProjectionPicture::mouseDoubleClickEvent(QMouseEvent *)
{scaleFactor = 1;currentStepScaleFactor = 1;verticalOffset = 0;horizontalOffset = 0;update();
}bool CProjectionPicture::gestureEvent(QGestureEvent *event)
{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;
}void CProjectionPicture::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();horizontalOffset += delta.x();verticalOffset += delta.y();update();
}void CProjectionPicture::pinchTriggered(QPinchGesture *gesture)
{QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();if (changeFlags & QPinchGesture::ScaleFactorChanged) {currentStepScaleFactor = gesture->totalScaleFactor();}if (gesture->state() == Qt::GestureFinished) {scaleFactor *= currentStepScaleFactor;currentStepScaleFactor = 1;}update();
}void CProjectionPicture::resizeEvent(QResizeEvent*e)
{update();QWidget::resizeEvent(e);
}// 上/下/左/右键向各个方向移动、加/减键进行缩放
void CProjectionPicture::keyPressEvent(QKeyEvent *event)
{switch (event->key()) {qDebug() << event->key();case Qt::Key_Up:translate(QPointF(0, -5));  // 上移break;case Qt::Key_Down:translate(QPointF(0, 5));  // 下移break;case Qt::Key_Left:translate(QPointF(-5, 0));  // 左移break;case Qt::Key_Right:translate(QPointF(5, 0));  // 右移break;case Qt::Key_Plus:  // 放大zoomIn();break;case Qt::Key_Minus:  // 缩小zoomOut();break;default:QWidget::keyPressEvent(event);}QWidget::keyPressEvent(event);
}// 平移
void CProjectionPicture::mouseMoveEvent(QMouseEvent *event)
{if (m_bMouseTranslate){QPointF mouseDelta = event->pos() - m_lastMousePos;translate(mouseDelta);}m_lastMousePos = event->pos();QWidget::mouseMoveEvent(event);
}void CProjectionPicture::mousePressEvent(QMouseEvent *event)
{qDebug() << "CProjectionPicture::mousePressEvent";if (event->button() == m_translateButton) {m_bMouseTranslate = true;m_lastMousePos = event->pos();setCursor(Qt::OpenHandCursor);}QWidget::mousePressEvent(event);
}void CProjectionPicture::mouseReleaseEvent(QMouseEvent *event)
{if (event->button() == m_translateButton){m_bMouseTranslate = false;setCursor(Qt::ArrowCursor);}QWidget::mouseReleaseEvent(event);
}// 放大/缩小
void CProjectionPicture::wheelEvent(QWheelEvent *event)
{qDebug() << "CProjectionPicture::wheelEvent";
//    QPoint numPixels = event->pixelDelta();QPoint scrallAmount = event->angleDelta();if(scrallAmount.y() > 0){zoomIn();}else if(scrallAmount.y() < 0){zoomOut();}QWidget::wheelEvent(event);
}// 放大
void CProjectionPicture::zoomIn()
{zoom(1 + m_zoomDelta);
}// 缩小
void CProjectionPicture::zoomOut()
{zoom(1 - m_zoomDelta);
}// 缩放 - scaleFactor:缩放的比例因子
void CProjectionPicture::zoom(float scale)
{scaleFactor *= scale;update();
}// 平移
void CProjectionPicture::translate(QPointF delta)
{horizontalOffset += delta.x();verticalOffset += delta.y();update();
}

本文参考:http://blog.csdn.net/liang19890820/article/details/53543017

Qt QWidget实现手势缩放和平移(一)相关推荐

  1. Qt QWidget实现手势缩放和平移(二)

    上一篇文章中讲到了QWidget实现手势缩放和平移,通过QGestureEvent来捕捉手势操作,但是这种方式不一定能通用,比如像教学用的电子白板上,是红外触控感应,并不能通过QGestureEven ...

  2. Android 图片随着手势缩放,平移,并且支持多点触控

    效果图: 现在app中,图片预览功能肯定是少不了的,用户基本已经形成条件反射,看到小图,点击看大图,看到大图两个手指开始进行放大,放大后,开始移动到指定部位~~~ 想要做到图片支持多点触控,自由的进行 ...

  3. Qt实现触摸屏手势控制

    作者 QQ群:852283276 微信:arm80x86 微信公众号:青儿创客基地 B站:主页 https://space.bilibili.com/208826118 参考 Qt QWidget实现 ...

  4. Unity 触屏手势控制Camera平移旋转缩放

    Unity 触屏手势控制Camera平移旋转缩放 实现思路 单点触屏,位移增量控制相机平移: 两点触屏,两点位移控制相机前后移动(缩放):两点中一点不位移控制相机绕点旋转: 实现需要的API Touc ...

  5. 手势控制控件 的缩放,平移和旋转:

    手势控制控件的缩放,平移和旋转: mapView是要移动的控件,TouchLayout是手势控制的区域,具体代码如下: touchLayout.setOnTouchListener(new Touch ...

  6. js实现移动端图片预览:手势缩放, 手势拖动,双击放大...

    原文:js实现移动端图片预览:手势缩放, 手势拖动,双击放大... 前言 本文将介绍如何通过js实现移动端图片预览,包括图片的 预览模式,手势缩放,手势拖动,双击放大等基本功能: 扫码查看示例效果: ...

  7. Qt quick基础2(包含平移旋转放缩以及qml控件大写开头啊)

    Qt quick基础2(包含平移旋转放缩以及qml控件大写开头啊) 目录 Qt quick基础2(包含平移旋转放缩以及qml控件大写开头啊) 前言 简单的平移.旋转和放缩 其他元素的一些基本使用 qm ...

  8. Android 视频手势缩放与回弹动效实现(一)

    文章目录 Android 视频手势缩放与回弹动效实现(一) 1. 功能需求 2. 实现原理 2.1 如何检测手势缩放? 1. View.onTouchEvent关键代码 2. ScaleGesture ...

  9. 安卓图片手势缩放、旋转、移动

    两个ImageView都可以手势缩放.旋转.移动 自定义ImageView一 import android.content.Context; import android.graphics.Matri ...

最新文章

  1. 使用nginx阻止别人域名绑定到自己的IP上
  2. Javascript 返回上一页
  3. debian卸载vmware
  4. php 组合模式,php设计模式(十三)透明组合模式
  5. 解决IE8下body{ overflow:hidden;}无效的解决办法
  6. HomeWindowsYesPlayMusic – 一个好看的第三方xx云音乐客户端 YesPlayMusic
  7. php的 静态变量,PHP之static静态变量详解
  8. [微信开发] - 关于测试号以及消息发送及回复
  9. java 筛选地区语句_Java选择语句
  10. CentOS 安装WildFly Jboss10
  11. Redis的实现原理
  12. 面试官:编写一个 SQL 查询,找出每个部门工资第二高的员工
  13. 【OCP|052】OCP题库更新,052最新考题及答案整理-第10题
  14. 这20个常规Python语法你都搞明白了吗?
  15. 技术人观点:开发人员在处理云应用时该注意什么?
  16. S7-300中各个块之间的联系以及OB块的功能和应用场合
  17. Android:Json数据转换成Map
  18. CMMB手机电视到了芯片企业创新的时侯
  19. 20 年前,亚马逊就推出了大数据杀熟算法
  20. 长连接与短链接的区别

热门文章

  1. Attention函数手册
  2. 互联网1分钟 | 0117 IBM入驻上海张江人工智能岛;IoT业务将成为小米新支撑点
  3. Android 截屏监听(截图分享功能实现)
  4. 【bzoj1369】[Baltic2003]Gem(树形dp+结论)
  5. metamask中的import account的代码实现
  6. Spring的Bean的初始化
  7. 单点登录之实战CAS5.1.x(六)——REST协议
  8. 【POI】对于POI无法处理超大xls等文件,官方解决方法【已解决】【多线程提升速率待定】...
  9. golang(5):编写WebSocket服务,client和html5调用
  10. [C] 跨平台使用Intrinsic函数范例1——使用SSE、AVX指令集 处理 单精度浮点数组求和(支持vc、gcc,兼容Windows、Linux、Mac)...