Qt 2D绘图之五:图形视图框架的结构、坐标系统和框架间的事件处理与传播

news2024/12/12 17:13:53

参考文章链接:
Qt 2D绘图之五:图形视图框架的结构和坐标系统
Qt 2D绘图之六:图形视图框架的事件处理与传播

图形视图框架的结构

在前面讲的基本绘图中,我们可以自己绘制各种图形,并且控制它们。但是,如果需要同时绘制很多个相同或不同的图形,并且要控制它们的移动、检测它们的碰撞和叠加;或者我们想让自己绘制的图形可以拖动位置、进行缩放和旋转等操作。实现这些功能,要是还使用以前的方法,那么会十分困难。解决这些问题,可以使用Qt提供的图形视图框架。

图形视图(Graphics View)框架结构的主要特点如下:

  • 图形视图(Graphics View)可以对大量定制的2D图形项进行管理和相互作用。视图部件可以让所有图形项可视化,它还提供了缩放和旋转功能
  • 框架中包含了一个事件传播构架,提供了和场景中的图形项进行精确的双精度交互的能力,图形项可以处理键盘事件,鼠标的按下、移动、释放和双击事件,还可以跟踪鼠标的移动
  • 图形视图框架使用一个BSP(Binary Space Partitioning)树来快速发现图形项,也正是因为如此,它可以实时显示一个巨大的场景,甚至包含上百万个图形项
    图形视图框架结构中,系统可以利用Qt绘图系统的反锯齿、OpenGL工具来改善绘图性能。

图形视图结构主要包含三部分:

  • 场景(Scene) :QGraphicsScene类
  • 视图(View) :QGraphicsView类
  • 图形项(Item):QGraphicsItem类

场景(Scene)

场景是图形项QGraphicsItem对象的容器,其主要完成的工作包括:
(1)提供用于管理大量图形项的快速接口
(2)传播事件给每一个图形项
(3)管理图形项的状态(如选择和焦点处理);
(4)提供无变换的渲染功能,主要用于打印

下面是一些QGraphicsScene的常用函数

  • 可以调用QGraphicsScene: :addItem()函数将图形项添加到场景中,然后调用任意一个图形项发现函数来检索添加的图形项。
  • QGraphicsScene::items()函数和其他几个重载函数可以返回符合条件的所有图形项。这些图形项不是与指定的点、矩形、多边形或者矢量路径相交,就是包含在它们之中。
  • QGraphicsScene::itemAt()函数返回指定点的最上面的图形项。所有的图形项发现函数返回的图形项都是使用递减顺序(例如第一个返回的图形项在最上面,最后返回的图形项在最下面)。
  • 如果要从场景中删除一个图形项,可以使用QGraphicsScene::Removeltem()函数。
  • 可以通过向QGraphicsScene::setSelectionArea()函数中传递一个任意的形状来选择场景中指定的图形项。
  • 如果要获取当前选取的所有图形项的列表,可以使用QGraphicsScene:: selectedltems()函数。
  • 另外可以调用QGraphicsScene:: setFocusItem()或者 QGraph­icsScene:: setFocus( )函数来为一个图形项设置焦点,调用QGraphicsScene:: focusItem()函数来获取当前获得焦点的图形项。
  • QGraphicsScene:: render()函数将场景中的一部分渲染到一个绘图设备上。

下面先来看一个最简单的例子。新建空的Qt项目(Empty qmake Project),项目名称为myscene。然后在这个项目中添加新的C++源文件,命名为main.cpp。添加完成后首先在myscene.pro文件中添加一行代码:

QT += widgets

然后将main.cpp的内容更改如下。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QDebug>

int main(int argc,char* argv[ ])
{
   
    QApplication app(argc,argv);

    //新建场景
    QGraphicsScene scene;
    //创建矩形图形项
    QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 100, 100);
    //将图形项添加到场景中
    scene.addItem(item);
    //输出(50, 50)点处的图形项
    qDebug() << scene.itemAt(50,50,QTransform());

    return app.exec();
}

这里先创建了一个场景,然后创建了一个矩形图形项,并且将该图形项添加到了场景中。然后使用itemAt()函数来返回指定坐标处最顶层的图形项,这里返回的就是刚才添加的矩形图形项。现在可以运行程序,不过因为还没有设置视图,所以不会出现任何图形界面,这时可以在应用程序输出栏中看到输出的项目的信息如下:

QGraphicsItem(0x161015c8, pos=0,0)

视图(View)

QGraphicsView提供了视图部件,它用来使场景中的内容可视化可以连接多个视图到同一个场景来为相同的数据集提供多个视口

下面是一些QGraphicsView:的常用函数

  • 视图部件是一个可滚动的区域,提供了一个滚动条来浏览大的场景,可以使用setDragMode()函数以QGraphicsView::SCrollHandDrag为参数来使光标变为手掌形状,从而可以拖动场景。
  • 如果设置 setDragMode()的参数为QGraphicsView::RubberBandDrag,那么可以在视图上使用 鼠标拖出橡皮筋框来选择图形项。
  • 默认的QGraphicsView提供了一个QWidget作为视口部件,如果要使用OpenGL进行植染,可以调用QGraphicsView::setViewport()设置QOpenGLWidget作为视口。QGraphicsView会获取视口部件的拥有权(ownership)。

在前面的程序中先添加头文件# include ,然后在主函数中 “return app. exec();”一行代码前继续添加如下代码:

//为场景创建视图
QGraphicsView view(&scene);
//设置场景的前景色
view.setForegroundBrush(QColor(255, 255, 0, 100));
//设置场景的背景图片
view.setBackgroundBrush(QPixmap("../myScene/background.png"));
view.resize(400, 300);
view.show();

这里新建了视图部件,并指定了要可视化的场景。然后为该视图设置了场景前景色和背景图片。**一个场景分为3层:图形项层(ItemLayer)、前景层(ForegroundLayer)和背景层(BackgroundLayer)。场景的绘制总是从背景层开始,然后是图形项层,最后是前景层。前景层和背景层都可以使用QBrush进行填充,比如使用渐变和贴图等。**这里的前景色设置为半透明的黄色,当然也可以设置为其他的填充。这里要提示一下,其实使用好前景色可以实现很多特殊的效果,比如使用半透明的黑色便可以实现夜幕降临的效果。

代码中使用了 QGraphicsView类中的函数来设置场景中的背景和前景,其实也可以使用QGraphicsScene中的同名函数来实现,不过它们的效果并不完全 一样。如果使用QGraphicsScene对象设置了场景背景或者前景,那么对所有关联了该场景的视图都有效,而QGraphicsView对象设置的场景的背景或者前景,只对它本身对应的视图有效。

运行程序,效果如下图所示。可以看到矩形图形项和背景图片都是在视图中间部分进行绘制的,这个问题会在后面的坐标系统部分详细讲解。
在这里插入图片描述

图形项

QGraphicsItem是场景中图形项的基类。图形视图框架为典型的形状提供了标准的图形项,比如矩形(QGraphicsRectlem)、椭圆(QGraphicsEllipseltem)和文本项(QGraphicsTextltem)。不过,只有编写自定义的图形项时才能发挥QGraphicsItem的强大功能。
QGraphicsItem主要支持以下功能:

  • 鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件;
  • 键盘输入焦点和键盘事件;
  • 拖放事件;
  • 分组,使用QGraphicsItemGroup通过parent-child关系来实现

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

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

相关文章

大模型面试题:P-tuning、Prompt-tuning和Prefix-tuning区别是什么?

我整理了1000道算法面试题&#xff0c;可以在下面的地方获取&#xff0c;面试题还是有点多的 P-tuning、Prompt-tuning和Prefix-tuning区别是什么&#xff1f; prefix-tuning对比P-tuning&#xff1a;Prefix-Tuning是将额外的embedding加在开头&#xff0c;看起来更像模仿Inst…

数据结构初阶之顺序表的介绍与动态顺序表的实现

一、线性表 线性表&#xff08;linear list&#xff09;是由 n 个具有相同特性的数据元素组成的有限序列。线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续…

学习日志020---qt信号与槽

作业 import sysfrom PySide6.QtWidgets import QApplication, QWidget,QPushButton,QLineEditfrom Form import Ui_Form from second import Ui_second from PySide6.QtCore import Qtclass MyWidget(QWidget,Ui_Form):def __init__(self):super().__init__()self.setupUi(se…

大语言模型技术相关知识-笔记整理

系列文章目录 这个系列攒了很久。主要是前段之间面试大语言模型方面的实习&#xff08;被拷打太多次了&#xff09;&#xff0c;然后每天根据面试官的问题进行扩展和补充的这个笔记。内容来源主要来自视频、个人理解以及官方文档中的记录。方便后面的回顾。 文章目录 系列文章…

9.13[debug]

这个错误表明 Git 尝试通过 HTTPS 协议连接到 Gitee 上的仓库时&#xff0c;实际上却尝试连接到了本地的 127.0.0.1&#xff08;即 localhost&#xff09;的 7890 端口&#xff0c;这通常是因为 HTTP 代理配置错误或全局 Git 配置中的代理设置不正确 如果这些命令返回了代理设…

Android笔记(三十四):onCreate执行Handler.post在onResume后才能执行?

背景 偶然发现一个点&#xff0c;就是在onCreate执行Handler.post在onResume后才执行&#xff0c;以下是测试代码 多次运行的结果一致&#xff0c;为什么execute runnable不是在onCreate和onResume之间执行的呢&#xff0c;带着疑问撸了一遍Activity启动流程 关键源码分析 …

Python基于 Opencv+wxPython 的人脸识别上课考勤系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Alogrithm:费式数列

1. 说明 Fibonacci 为1200年代的欧洲数学家&#xff0c;在他的著作中曾经提到&#xff1a;「若有一只免子每个月生一只小免子&#xff0c;一个月后小免子也开始生产。起初只有一只免子&#xff0c;一个月后就有两只免子&#xff0c;二个月后有三只免子&#xff0c;三个月后有五…

【机器学习】机器学习的基本分类-监督学习-决策树-CART(Classification and Regression Tree)

CART&#xff08;Classification and Regression Tree&#xff09; CART&#xff08;分类与回归树&#xff09;是一种用于分类和回归任务的决策树算法&#xff0c;提出者为 Breiman 等人。它的核心思想是通过二分法递归地将数据集划分为子集&#xff0c;从而构建一棵树。CART …

[高阶数据结构七]跳表的深度剖析

1.前言 跳表是一种查找结构&#xff0c;它有着与红黑树、AVL树和哈希表相同的作用&#xff0c;那么已经学习了红黑树和哈希表这种效率高的数据结构&#xff0c;那么为什么还需要学习跳表呢&#xff1f;--请听我娓娓道来。 本章重点&#xff1a; 本章着重讲解跳表的概念&#x…

基于MATLAB的信号处理工具:信号分析器

信号&#xff08;或时间序列&#xff09;是与特定时间相关的一系列数字或测量值&#xff0c;不同的行业和学科将这一与时间相关的数字序列称为信号或时间序列。生物医学或电气工程师会将其称为信号&#xff0c;而统计学家或金融定量分析师会使用时间序列这一术语。例如&#xf…

Linux Shell 脚本:一键在 Ubuntu 系统中打开和关闭网络代理

文章目录 shell脚本使用说明验证设置 shell脚本 以下是一个简单的 Shell 脚本&#xff0c;用于在 Ubuntu 系统中打开和关闭网络代理开关 #!/bin/bash# 检查传入的参数 if [ "$#" -ne 1 ]; thenecho "Usage: $0 <1|0>"echo "1: Enable proxy (…

Android ConstraintLayout 约束布局的使用手册

目录 前言 一、ConstraintLayout基本介绍 二、ConstraintLayout使用步骤 1、引入库 2、基本使用&#xff0c;实现按钮居中。相对于父布局的约束。 3、A Button 居中展示&#xff0c;B Button展示在A Button正下方&#xff08;距离A 46dp&#xff09;。相对于兄弟控件的约束…

【AI工具】强大的AI编辑器Cursor详细使用教程

目录 一、下载安装与注册 二、内置模型与配置 三、常用快捷键 四、项目开发与问答 五、注意事项与技巧 参考资料 近日&#xff0c;由四名麻省理工学院&#xff08;MIT&#xff09;本科生共同创立的Anysphere公司宣布&#xff0c;其开发的AI代码编辑器Cursor在成立短短两年…

Linux-GPIO应用编程

本章介绍应用层如何控制 GPIO&#xff0c;譬如控制 GPIO 输出高电平、或输出低电平。 只要是用到GPIO的外设&#xff0c;都有可能用得到这些操作方法。 照理说&#xff0c;GPIO的操作应该是由驱动层去做的&#xff0c;使用寄存器操作或者GPIO子系统之类的框架。 但是&#xff0…

前端开发 之 15个页面加载特效下【附完整源码】

文章目录 十二&#xff1a;铜钱3D圆环加载特效1.效果展示2.HTML完整代码 十三&#xff1a;扇形百分比加载特效1.效果展示2.HTML完整代码 十四&#xff1a;四色圆环显现加载特效1.效果展示2.HTML完整代码 十五&#xff1a;跷跷板加载特效1.效果展示2.HTML完整代码 十二&#xff…

STM32 DMA直接存储器存取原理及DMA转运模板代码

DMA简介&#xff1a; 存储器映像&#xff1a; 注意&#xff1a;FLASH是只读的&#xff0c;DMA不能写入&#xff0c;但是可以读取写到其他存储器里 变量是存在运行内存SRAM里的&#xff0c;常量&#xff08;const&#xff09;是放在程序存储器FLASH里的 DMA框图&#xff1a; …

transformers实现一个检索机器人(一)

简介 检索机器人是一种能够自动搜索和提供信息的系统&#xff0c;它可以帮助我们快速找到需要的信息。这类机器人通常使用自然语言处理&#xff08;NLP&#xff09;技术来理解用户的查询&#xff0c;并利用搜索引擎或数据库来获取相关信息。 那么我们要通过transforme实现什么…

开源ISP介绍(2)————嵌入式Vitis搭建

Vivado搭建参考前一节Vivado基于IP核的视频处理框架搭建&#xff1a; 开源ISP介绍&#xff08;1&#xff09;——开源ISP的Vivado框架搭建-CSDN博客 导出Hardware 在vivado中导出Hardware文件&#xff0c;成功综合—实现—生成比特流后导出硬件.xsa文件。&#xff08;注意导…

力扣-图论-2【算法学习day.52】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非…