QGraphicsView(平移/缩放/旋转)

简述

Graphics View提供了一个平台,用于大量自定义 2D 图元的管理与交互,框架包括一个事件传播架构,支持场景 Scene 中的图元 Item 进行精确的双精度交互功能。Item 可以处理键盘事件、鼠标按下、移动、释放和双击事件,同时也能跟踪鼠标移动。

和 Google 地图一样,在管理大量 Item 的时候,通常需要 View 具有交互(平移/缩放/旋转)功能。

交互式 QGraphicsView

便于以后复用,实现一个交互式 QGraphicsView - InteractiveView。

主要功能包括:

  • 平移: 
    • 方式一:鼠标左键按下,然后移动
    • 方式二:按下上/下/左/右键分别向各个方向移动
  • 缩放: 
    • 方式一:鼠标滚轮向上滚动放大,向下滚动缩小
    • 方式二:按加号键(带 Shift)进行放大,按减号键缩小
  • 旋转:按空格键逆时针旋转,回车键顺时针旋

效果

源码

interactive_view.h

#ifndef INTERACTIVE_VIEW_H
#define INTERACTIVE_VIEW_H#include <QGraphicsView>class QWheelEvent;
class QKeyEvent;class InteractiveView : public QGraphicsView
{Q_OBJECT
public:explicit InteractiveView(QWidget *parent = 0);// 平移速度void setTranslateSpeed(qreal speed);qreal translateSpeed() const;// 缩放的增量void setZoomDelta(qreal delta);qreal zoomDelta() const;protected:// 上/下/左/右键向各个方向移动、加/减键进行缩放、空格/回车键旋转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;// 放大/缩小void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;public Q_SLOTS:void zoomIn();  // 放大void zoomOut();  // 缩小void zoom(float scaleFactor); // 缩放 - scaleFactor:缩放的比例因子void translate(QPointF delta);  // 平移private:Qt::MouseButton m_translateButton;  // 平移按钮qreal m_translateSpeed;  // 平移速度qreal m_zoomDelta;  // 缩放的增量bool m_bMouseTranslate;  // 平移标识QPoint m_lastMousePos;  // 鼠标最后按下的位置qreal m_scale;  // 缩放值
};#endif // INTERACTIVE_VIEW_H

平移速度默认为 1.0,可以使用 setTranslateSpeed() 来改变。缩放的增量大小也可以使用 setZoomDelta() 改变。

interactive_view.cpp

#include <QWheelEvent>
#include <QKeyEvent>
#include "interactive_view.h"#define VIEW_CENTER viewport()->rect().center()
#define VIEW_WIDTH  viewport()->rect().width()
#define VIEW_HEIGHT viewport()->rect().height()InteractiveView::InteractiveView(QWidget *parent): QGraphicsView(parent),m_translateButton(Qt::LeftButton),m_scale(1.0),m_zoomDelta(0.1),m_translateSpeed(1.0),m_bMouseTranslate(false)
{// 去掉滚动条setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);setCursor(Qt::PointingHandCursor);setRenderHint(QPainter::Antialiasing);setSceneRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);centerOn(0, 0);
}// 平移速度
void InteractiveView::setTranslateSpeed(qreal speed)
{// 建议速度范围Q_ASSERT_X(speed >= 0.0 && speed <= 2.0,"InteractiveView::setTranslateSpeed", "Speed should be in range [0.0, 2.0].");m_translateSpeed = speed;
}qreal InteractiveView::translateSpeed() const
{return m_translateSpeed;
}// 缩放的增量
void InteractiveView::setZoomDelta(qreal delta)
{// 建议增量范围Q_ASSERT_X(delta >= 0.0 && delta <= 1.0,"InteractiveView::setZoomDelta", "Delta should be in range [0.0, 1.0].");m_zoomDelta = delta;
}qreal InteractiveView::zoomDelta() const
{return m_zoomDelta;
}// 上/下/左/右键向各个方向移动、加/减键进行缩放、空格/回车键旋转
void InteractiveView::keyPressEvent(QKeyEvent *event)
{switch (event->key()) {case Qt::Key_Up:translate(QPointF(0, -2));  // 上移break;case Qt::Key_Down:translate(QPointF(0, 2));  // 下移break;case Qt::Key_Left:translate(QPointF(-2, 0));  // 左移break;case Qt::Key_Right:translate(QPointF(2, 0));  // 右移break;case Qt::Key_Plus:  // 放大zoomIn();break;case Qt::Key_Minus:  // 缩小zoomOut();break;case Qt::Key_Space:  // 逆时针旋转rotate(-5);break;case Qt::Key_Enter:  // 顺时针旋转case Qt::Key_Return:rotate(5);break;default:QGraphicsView::keyPressEvent(event);}
}// 平移
void InteractiveView::mouseMoveEvent(QMouseEvent *event)
{if (m_bMouseTranslate){QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_lastMousePos);translate(mouseDelta);}m_lastMousePos = event->pos();QGraphicsView::mouseMoveEvent(event);
}void InteractiveView::mousePressEvent(QMouseEvent *event)
{if (event->button() == m_translateButton) {// 当光标底下没有 item 时,才能移动QPointF point = mapToScene(event->pos());if (scene()->itemAt(point, transform()) == NULL)  {m_bMouseTranslate = true;m_lastMousePos = event->pos();}}QGraphicsView::mousePressEvent(event);
}void InteractiveView::mouseReleaseEvent(QMouseEvent *event)
{if (event->button() == m_translateButton)m_bMouseTranslate = false;QGraphicsView::mouseReleaseEvent(event);
}// 放大/缩小
void InteractiveView::wheelEvent(QWheelEvent *event)
{// 滚轮的滚动量QPoint scrollAmount = event->angleDelta();// 正值表示滚轮远离使用者(放大),负值表示朝向使用者(缩小)scrollAmount.y() > 0 ? zoomIn() : zoomOut();
}// 放大
void InteractiveView::zoomIn()
{zoom(1 + m_zoomDelta);
}// 缩小
void InteractiveView::zoomOut()
{zoom(1 - m_zoomDelta);
}// 缩放 - scaleFactor:缩放的比例因子
void InteractiveView::zoom(float scaleFactor)
{// 防止过小或过大qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();if (factor < 0.07 || factor > 100)return;scale(scaleFactor, scaleFactor);m_scale *= scaleFactor;
}// 平移
void InteractiveView::translate(QPointF delta)
{// 根据当前 zoom 缩放平移数delta *= m_scale;delta *= m_translateSpeed;// view 根据鼠标下的点作为锚点来定位 scenesetTransformationAnchor(QGraphicsView::AnchorUnderMouse);QPoint newCenter(VIEW_WIDTH / 2 - delta.x(),  VIEW_HEIGHT / 2 - delta.y());centerOn(mapToScene(newCenter));// scene 在 view 的中心点作为锚点setTransformationAnchor(QGraphicsView::AnchorViewCenter);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/568907.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

地推网推拉新是什么意思?地推网推拉新区别最全介绍

地推是相对于网推的&#xff0c;主要是通过线下推广&#xff0c;来吸引客户注册等拉新操作&#xff0c;有时会发一些小礼物之类的&#xff0c;在之前地推是最早获取新用户的方式&#xff0c;是最有效的拉新方式&#xff0c;直到现在地推仍是各类互联网公司和品牌商家&#xff0…

论文阅读之PeriodicLoRA: Breaking the Low-Rank Bottleneck in LoRA Optimization(2024)

文章目录 论文地址主要内容主要贡献模型图技术细节实验结果 论文地址 PeriodicLoRA: Breaking the Low-Rank Bottleneck in LoRA Optimization 主要内容 这篇文章的主要内容是介绍了一种名为PeriodicLoRA&#xff08;PLoRA&#xff09;的参数高效微调&#xff08;Parameter-…

sdrangel下载与部署for windows

下载 https://github.com/f4exb/sdrangel 在其目录下新建build文件 部署 打开cmake软件,修改如下 点击下面Configure,选择对应vs版本 点击finish,按照提示报错信息配置即可 ARCH_OPT=SSE4_2 DEBUG_OUTPUT

qt table 简易封装,样式美化,以及 合并表格和颜色的区分 已解决

在需求中&#xff0c; 难免会使用 table 进行渲染窗口&#xff0c;做一个简单的封装。美化表格最终效果&#xff01;&#xff01;&#xff01; 代码部分 // 显示 20行 20列CCendDetailsInfoTableWidget* table new CCendDetailsInfoTableWidget(20,10);for (int i 0; i < …

基于Springboot Vue医院管理系统+数据库脚本+文档(万字)

项目效果视频: 基于Springboot Vue医院管理系统 一、 项目介绍 角色&#xff1a;管理员、患者、医生 基于springboot vue实现的医院管理系统&#xff0c;有管理员、医生和患者三种角色。系统拥有丰富的功能&#xff0c;能够满足各类用户的需求&#xff0c;系统提供了登录和注册…

[Qt学习笔记]Qt实现自定义控件SwitchButton开关按钮

1、功能介绍 在项目UI中使用较多的打开/关闭的开关按钮&#xff0c;一般都是找图片去做效果&#xff0c;比如说如下的图像来表征打开或关闭。 如果想要控件有打开/关闭的动画效果或比较好的视觉效果&#xff0c;这里就可以使用自定义控件&#xff0c;使用Painter来绘制控件。软…

001-Windows下PyTorch极简开发环境配置

本节介绍Windows系统下配置一套基于Pytorch框架的极简深度学习开发环境。 目录 0.1 缘起 0.2 准备 1.1 安装Anaconda 1.2 安装CUDA和cudnn &#xff08;1&#xff09;确定CUDA版本 &#xff08;2&#xff09;安装CUDA &#xff08;3&#xff09;安装cudnn 1.3 安装Pyt…

论文阅读--临床驱动的多标签医学图像分类中的三元组注意力与双池对比学习---TA-DCL

来源&#xff1a;https://github.com/ZhangYH0502/TA-DCL. 模型结合了两种技术&#xff1a;三元组注意力&#xff08;Triplet attention&#xff09;和双池对比学习&#xff08;Dual-pool contrastive learning&#xff09;。这个模型是为了解决临床应用中多标签医学图像分类问…

中等职业学校大数据课程建设方案

大数据产业是以数据及数据所蕴含的信息价值为核心生产要素&#xff0c;通过数据技术、数据产品、数据服务等形式&#xff0c;使数据与信息价值在各行业经济活动中得到充分释放的赋能型产业。 大数据产业定义一般分为核心业态、关联业态、衍生业态三大业态。 一、专…

C语言 青蛙跳台阶问题

目录 ​编辑 1.问题描述 2.问题分析 3.全部代码 4.结语 1.问题描述 一只青蛙可以一次跳一级台阶&#xff0c;也可以一次跳两级台阶&#xff0c;如果青蛙要跳上n级台阶有多少种跳法&#xff1f; 2.问题分析 当台阶只有一级时&#xff0c;只能跳一级&#xff0c;所以只有一…

2015年认证杯SPSSPRO杯数学建模D题(第一阶段)城市公共自行车全过程文档及程序

2015年认证杯SPSSPRO杯数学建模 D题 城市公共自行车 原题再现&#xff1a; 城市交通问题直接影响市民的生活和工作。在地形平坦的城市&#xff0c;公共自行车出行系统是一种很好的辅助手段。一般来说&#xff0c;公共自行车出行系统由数据中心、驻车站点、驻车桩、自行车&…

VR全景为中小型企业发展带来了什么优势?

有研究数据表明&#xff0c;今年前期中小型企业发展活力得以持续释放&#xff0c;在促进经济增长、稳定就业等方面发挥了重要作用。而在有关政策的支持下&#xff0c;加上各大媒体和具有影响力的企业带动下&#xff0c;VR全景凭借其新颖的展示方式备受瞩目。 那么VR全景为中小型…