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.mzph.cn/news/772828.shtml

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

相关文章

鸿蒙OS封装【axios 网络请求】(类似Android的Okhttp3)

Okhttp.ets /*** 网络请求*/ import axios from ohos/axios import httpConstants from ../net/HttpConstants import errorCode from ../utils/errorCode import toast from ../utils/ToastUtils import router from ../utils/RouterUtils import SPUtils from ../utils/SPUt…

毕马威:量子计算成未来3-5年重大挑战

毕马威&#xff08;KPMG&#xff09;是一家全球性的专业服务网络&#xff0c;其历史可追溯到19世纪末。作为“四大”会计师事务所之一&#xff0c;毕马威在审计、税务和咨询服务领域享有盛誉。公司在全球范围内拥有多个办事处&#xff0c;服务遍及各个行业&#xff0c;包括金融…

5.1 物联网RK3399项目开发实录-Android开发之ADB使用(wulianjishu666)

物联网项目开发实例&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/11VQMhHfIL9mZhNlls4wmjw?pwd0gfa 1. ADB 使用 1.1. 前言 ADB&#xff0c;全称 Android Debug Bridge&#xff0c;是 Android 的命令行调试工具&#xff0c;可以完成多种功能&#xff0c;如跟踪系…

CentOS Stream 8系统配置阿里云YUM源

Linux运维工具-ywtool 目录 一.系统环境二.修改yum文件2.1 CentOS-Stream-AppStream.repo2.2 CentOS-Stream-BaseOS.repo2.3 CentOS-Stream-Extras.repo 三.只有一个配置文件四.其他知识4.1 如果想要启用其他源,修改文件配置:enabled14.2 国内源链接 一.系统环境 CentOS Strea…

Linux一键式安装JDK、Mysql、Redis、Nginx(附带安装包,无需手动配置密码等)

安装包 新服务器安装前置准备 1. 设置系统时区 # 查看服务器时区 timedatectl # 设置服务器时区为上海 timedatectl set-timezone Asia/Shanghai # 设置系统时间为“2021-3-19 11:00:00” date -s "2021-3-19 11:00:00" # 查看校准后的系统时间 date …

[C++]内联函数(内联函数的概念,内联函数的特性,内联函数与宏的区别)

一、内联函数的概念 以inline修饰的的函数叫内联函数&#xff0c;编译时C编译器会在调用内联函数的位置将内联函数展开&#xff0c;内联函数没有调用函数参数压栈的开销&#xff0c;内联函数可以提高程序的运行效率。 例子&#xff1a; 没有使用内联函数 使用内联函数&#xff…

uniapp小程序中onShareAppMessage(OBJECT)实现带参数的分享功能

一、引言 小程序中用户点击分享后&#xff0c;在 js 中定义 onShareAppMessage 处理函数&#xff08;和 onLoad 等生命周期函数同级&#xff09;&#xff0c;设置该页面的分享信息。 用户点击分享按钮的时候会调用。这个分享按钮可能是小程序右上角原生菜单自带的分享按钮&…

【SpringBoot整合系列】SpringBoot3.x整合Swagger

目录 产生背景官方解释&#xff1a;作用SpringBoot3整合Swagger注意事项swagger3 常用注解SpringBoot3.x整合Swagger1.创建工程(jdk:17,boot:3.2.4)2.引入pom依赖3.application.yml添加配置4.添加swagger3.0配置5.控制器层(Controller)6.模型层(Model)7.启动并测试【Get请求接口…

一、Spring Cloud(Base工程构建)

一、Spring Cloud&#xff08;Base工程构建&#xff09; 1.1 Spring Cloud 简述 1.1.1 Spring Cloud 版本推荐 在讲解 Spring Cloud 之前&#xff0c;首先推荐一下各个依赖的版本&#xff0c;以免出现版本错误 版本推荐 必须根据以上版本&#xff0c;否则可能会出现一些不…

鸿蒙harmonyOS常用基础标签、组件、事件等用法介绍

基础组件 text &#xff1a; 字体标签&#xff0c;汉字显示必须用字体组件包裹&#xff0c;规范规定&#xff0c;不写不显示image&#xff1a;图片标签&#xff0c;属性&#xff1a;src&#xff0c;路径相对路径…/方式button&#xff1a;按钮标签&#xff0c;属性&#xff1a…

Hana数据库 No columns were bound prior to calling SQLFetch or SQLFetchScroll

在php调用hana数据库的一个sql时报错了&#xff0c;查表结构的sql&#xff1a; select * from sys.table_columns where table_name VBAP SQLSTATE[SL009]: <<Unknown error>>: 0 [unixODBC][Driver Manager]No columns were bound prior to calling SQLFetch …

智能小程序开发 —— meature API 汇总(二)

resetStatistics 重置设备的统计数据。 注意&#xff1a;该方法会清空统计数据&#xff0c;请注意使用方式&#xff01; 请求参数 参数数据类型说明是否必填devIdstring设备 ID是 请求示例 // ray-js/ray^1.2.12 import {resetStatistics} from ray-js/ray;resetStatisti…

基于SpringBoot和Leaflet的行政区划地图掩膜效果实战

目录 前言 一、掩膜小知识 1、GIS掩膜的实现原理 2、图层掩膜流程 二、使用插件 1、leaflet-mask介绍 2、核心代码解释 三、完整实例实现 1、后台逻辑实现 2、省级行政区划查询实现 3、行政区划定位及掩膜实现 4、成果展示 总结 前言 在之前的博客提过按空间矢量…

hadoop 常用命令

hadoop 常用命令 hadoop fs -mkdir /test hadoop fs -put /opt/frank/tb_test03.txt /test/ hadoop fs -ls /test/ hadoop fs -cat /test/tb_test03.txt hadoop fs -rm /test/tb_test03.txt hadoop dfs 也能使用、但不推荐&#xff0c;执行会提示&#xff1a; DEPRECATED: Us…

GPT大语言模型助力R语言开展数据统计分析

自2022年GPT&#xff08;Generative Pre-trained Transformer&#xff09;大语言模型的发布以来&#xff0c;它以其卓越的自然语言处理能力和广泛的应用潜力&#xff0c;在学术界和工业界掀起了一场革命。在短短一年多的时间里&#xff0c;GPT已经在多个领域展现出其独特的价值…

【STM32+HAL】I2C+DMA读取AS5600编码器

一、DMA的应用 有关更多DMA的应用&#xff0c;详见【STM32HAL】DMA应用 二、HAL库配置 1、开启I2C 开启对应DMA及中断 2、开启串口通信 至此&#xff0c;HAL库配置完毕 三、DMA版&#xff08;高效但不稳定&#xff09; 1、as5600.c #include "AS5600.h" #includ…

数据结构与算法 顺序表的基本运算

一、实验内容 编写一个程序实现&#xff0c;实现顺序表的各种基本运算&#xff08;假设顺序表的元素类型为char&#xff09;&#xff0c;并以此为基础设计一个程序完成下列功能&#xff1a; &#xff08;1&#xff09;初始化顺序表&#xff1b; &#xff08;2&#xff09;采…

docker 安装 kibana

使用Docker安装Kibana相对简单且易于管理。以下是使用Docker安装Kibana的基本步骤&#xff1a; 安装Docker&#xff1a; 确保你的CentOS系统上已经安装了Docker。如果没有&#xff0c;请按照以下命令安装&#xff1a; sudo yum install -y yum-utils device-mapper-persistent-…

用指针处理链表(二)

4建立动态链表 所谓建立动态链表是指在程序执行过程中从无到有地建立起一个链表&#xff0c;即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。 例11.8 写一函数建立一个有3名学生数据的单向动态链表。 先考虑实现此要求的算法(见图11.12)。 设3个指针变量:he…

企业级快速开发框架 nbsaas-boot 1.1.8-2024 发布了

<parent><groupId>com.nbsaas.boot</groupId><artifactId>nbsaas-boot</artifactId><version>1.1.8-2024</version> </parent> 本次更新内容 1. 重构代码生成器&#xff0c;采用类提取和字段提取两种方式&#xff0c;提取功能…