草庐IT

【QT】GraphicsView框架入门篇

黎明water 2023-04-03 原文

在Qt界面库中,对于需要绘制大量的、需要交互的图形,可使用Graphics View绘图架构,它是一种基于图形项(Graphics Item)的模型/视图模式,这种方式可以在一个场景中绘制大量图元项,且每个图元项都是可选择、可交互的。
GraphicsView 框架
在Graphics View绘图架构中,包括场景(Scene)、视图(View)、图形项(GraphicsItem)三部分。三部分用QGraphicsScene、QGraphicsView和QGraphicsItem三个类来表示。
(1)场景类:QGraphicsScene类
QGraphicsScene是一个放置图元的容器,是图形视图框架中的场景,拥有以下功能:
a、提供用于管理大量图形项(Items)的便捷接口。
b、分发事件给场景中的每一个图形项。
c、管理图形项(items)的状态,例如:选择和焦点处理等。
d、提供无变换的渲染功能,主要用于打印。
主要拥有以下方法:
场景是图形项QGraphicsItem对象的容器。调用QGraphicsScene::addItem()函数将图形项(Items)添加到场景中,然后调用众多的图形项查找函数来检索添加的图形项。
QGraphicsScene::items()函数和几个重载函数可以返回符合条件的所有图形项,这些图形项不是与指定的点、矩形、多边形或者矢量路径相交,就是包含在它们之中。
QGraphicsScene::itemAt()函数返回指定点的最上面的图形项(场景中的图形项可能会重叠)。所有的图形项寻找函数返回的图形项都是按照递减顺序进行的(例如第一个返回的图形项在最上面,最后返回的图形项在最下面)。
如果要从场景中删除一个图形项,可以使用QGraphicsScene::RemoveItem()函数。
场景允许通过QGraphicsScence::render()函数将场景的各个部分呈现到一个绘制设备中。
(2)视图类:QGraphicsView类
用于显示场景中的图元,QGraphicsView提供了视图widget,用来显示场景中的内容。可以将多个视图连接到同一个场景来为相同的数据集提供多个视口。
QGraphicsView是一个可滚动的区域控件,提供了一个滚动条来浏览大的场景,可以使用setDragMode()函数以QGraphicsView::ScrollHandDrag为参数来使光标变为手掌形状,从而可以拖动场景。如果设置setDragMode()的参数为QGraphicsView::RubberBandDrag,那么可以在视图上使用鼠标拖出橡皮筋框来选择图形项。
视图从键盘和鼠标接收输入事件,并将其转换成场景事件(在适当的地方将使用的坐标转换为场景坐标),然后将事件发送到可视化场景。使用QGraphicsView::transform(),视图可以转换场景的坐标系统。同样提供了转换视图和场景坐标的功能:QGraphicsView::mapToScene()和QGraphicsView::mapFromScene()。
默认的QGraphicsView提供了一个QWidget作为视口部件,如果要使用OpenGL进行渲染,可以调用QGraphicsView::setViewport()设置QGLWidget作为视口。QGraphicsView会获取视口部件的拥有权(ownership)。
(3)图元类:QGraphicsItem类
QGraphicsItem是场景中图形项的基类。图形视图框架为常见的典型形状提供了标准的图形项,例如:矩形(QGraphicsRectIem)、椭圆(QGraphicsEllipseItem)和文本项(QGraphicsTextItem)等。不过,只有当编写自定义图形项时才能发挥QGraphicsItem的强大功能。QGraphicsItem主要支持如下功能:
a、鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件
b、键盘输入焦点和键盘事件
c、拖放事件
d、分组,使用QGraphicsItemGroup通过parent-child关系来实现
e、碰撞检测
除此之外,图形项还可以存储自定义的数据,可以使用setData()进行数据存储,然后使用data()获取其中的数据。
一个场景分为三层:图形项层(ItemLayer)、前景层(ForegroundLayer)和背景层(BackgroundLayer)。场景的绘制总是从背景层开始,然后是图形项层,最后是前景层。前景层和背景层都可以使用QBrush进行填充,比如使用渐变和贴图等。这里的前景色设置为了半透明的白色,当然也可以设置为其他的填充。
GraphicsView 坐标系
Graphics View基于笛卡尔坐标系。item在场景中的位置与几何形状通过x,y坐标来表示。当使用未经变形的视图来观察场景时,场景中的一个单位等于屏幕上的一个像素。在Graphics View绘图架构中涉及到了3个坐标系,即场景坐标、视图坐标及图形项坐标。
1.场景坐标:对应QPainter的逻辑坐标,以场景的中心为原点,X轴正方向向右,Y轴正方向向下;

视图坐标:即窗口界面的物理坐标,单位是像素,其左上角为原点坐标,所有鼠标事件、拖拽事件最开始都使用视图坐标,为了和图元交互,需要转换坐标为场景坐标;
图形项坐标:图元存在于自己的本地坐标上,通常以图元的中心为原点,图元中心也是所有坐标变换的原点,图元坐标方向是X轴正方向向右,Y轴正方向向下(同上图)。
示例:

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include "math.h"

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

    QGraphicsScene scene;   // 定义一个场景,设置背景色为红色
    scene.setBackgroundBrush(Qt::red);

    QPen pen;   // 定义一个画笔,设置画笔颜色和宽度
    pen.setColor(QColor(0, 160, 230));
    pen.setWidth(10);

    QGraphicsRectItem *m_rectItem = new QGraphicsRectItem();   // 定义一个矩形图元
    m_rectItem->setRect(0, 0, 80, 80);
    m_rectItem->setPen(pen);
    m_rectItem->setBrush(QBrush(QColor(255, 0, 255)));
    m_rectItem->setFlag(QGraphicsItem::ItemIsMovable);

    QGraphicsLineItem *m_lineItem = new QGraphicsLineItem();    // 定义一个直线图元
    m_lineItem->setLine(QLineF(0, 0, 100, 100));
    m_lineItem->setPen(pen);
    m_lineItem->setFlag(QGraphicsItem::ItemIsMovable);

    QGraphicsPathItem *m_pathItem = new QGraphicsPathItem();    // 定义一个路径图元
    QPainterPath path;
    path.moveTo(90, 50);
    for (int i = 1; i < 5; ++i) {
        path.lineTo(50 + 40 * cos(0.8 * i * M_PI), 50 + 40 * sin(0.8 * i * M_PI));
    }
    path.closeSubpath();
    m_pathItem->setPath(path);
    m_pathItem->setPen(pen);
    m_pathItem->setFlag(QGraphicsItem::ItemIsMovable);

    QGraphicsPolygonItem *m_polygonItem = new QGraphicsPolygonItem();   // 定义一个多边形图元
    QPolygonF polygon;
    polygon << QPointF(-100.0, -150.0) << QPointF(-120.0, 150.0)
            << QPointF(320.0, 160.0) << QPointF(220.0, -140.0);
    m_polygonItem->setPolygon(polygon);
    m_polygonItem->setPen(pen);
    m_polygonItem->setFlag(QGraphicsItem::ItemIsMovable);

    scene.addItem(m_rectItem);      // 把矩形图元添加到场景
    scene.addItem(m_lineItem);      // 把直线图元添加到场景
    scene.addItem(m_pathItem);      // 把路径图元添加到场景
    scene.addItem(m_polygonItem);   // 把多边形图元添加到场景

    QGraphicsView view(&scene); // 定义一个视图,并把场景添加到视图
    view.resize(1024, 768);
    view.show();

    return a.exec();
}

有关【QT】GraphicsView框架入门篇的更多相关文章

  1. Qt Designer的简单使用 - 2

    在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q

  2. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  3. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  4. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  5. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  6. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  7. ruby - sinatra 框架的 MVC 模式 - 2

    我想开始使用“Sinatra”框架进行编码,但我找不到该框架的“MVC”模式。是“MVC-Sinatra”模式或框架吗? 最佳答案 您可能想查看Padrino这是一个围绕Sinatra构建的框架,可为您的项目提供更“类似Rails”的感觉,但没有那么多隐藏的魔法。这是使用Sinatra可以做什么的一个很好的例子。虽然如果您需要开始使用这很好,但我个人建议您将它用作学习工具,以对您来说最有意义的方式使用Sinatra构建您自己的应用程序。写一些测试/期望,写一些代码,通过测试-重复:)至于ORM,你还应该结帐Sequel其中(imho

  8. 区块链入门教程(6)--WeBASE-Front节点前置服务安装 - 2

    文章目录1.任务背景2.任务目标3.相关知识点4.任务实操4.1安装配置JDK4.2启动FISCOBCOS4.3下载解压WeBASE-Front4.4拷贝sdk证书文件4.5启动节点4.6访问节点4.7检查运行状态5.任务总结1.任务背景FISCOBCOS其实是有控制台管理工具,用来对区块链系统进行各种管理操作。但是对于初学者来说,还是可视化界面更友好,本节就来介绍WeBASE管理平台,这是一款微众银行开源的自研区块链中间件平台,可以降低区块链使用的门槛,大幅提高区块链应用的开发效率。微众银行是腾讯牵头设立的民营银行,在国内民营银行里还是比较出名的。微众银行参与FISCOBCOS生态建设,一定

  9. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  10. Simulink方法总结和避坑指南(一)——Simulink入门与基本调试方法 - 2

    文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景  最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。  在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记

随机推荐