【QT】GraphicsView、QGraphicsScene、QGraphicsEllipseItem的使用

article/2025/11/3 23:03:26

GraphicsView、QGraphicsScene、QGraphicsEllipseItem的使用

    • 前言
    • 实验目的
    • 重构GraphicsView类
    • 新建GraphicsView、QGraphicsScene层
    • 绘制Item图形控件
      • 绘制圆形
      • 绘制矩形
      • 绘制三角形
      • 绘制文字
      • 绘制直线
    • 组合、打散、前置和后置
      • 组合
      • 打散
      • 控件前置
      • 控件后置
    • 绑定功能事件
    • 总结

前言

对于绘图QT提供了两个类,这里简单介绍他俩(QPainter 和GraphicsView)的区别,QPainter英译过来就是画笔的意思,而这个类就是在一个平面绘画,画出来的画面不能后期更改,一般使用的地方就是制作一些炫酷的控件后续不做大的更改;QGraphicsView一般是用来做图形管理他可以对单个图进行管理操作,例如移动、放大缩小、删除以及增加真的图像模型。

QGraphicsView一般由三个部分组成:
1、GraphicsView:看法;看;视野;(个人的)意见;见解;态度;(理解或思维的)方法;方式;视域;视线
2、QGraphicsScene:场景;场面;情景;镜头;(尤指不愉快事件发生的)地点,现场;事件;片段
3、QGraphicsItem :项目;一件商品(或物品);一则,一条(新闻)
从上面的英文翻译可以理解GraphicsView是一个放置我们制作的控件的层,scene是负责管理和操作我们的控件层,而item就是我们的控件实物层;

实验目的

记录GraphicsView的简单使用和对自己的理解进行梳理,也可能有理解的不对的地方欢迎指正,下面开始代码实验。

重构GraphicsView类

在实际使用中我们一般需要重构GraphicsView类的的几个信号提供给我们操作图层的信号。

//鼠标移动事件:用来获取实时获取我们的鼠标所在的坐标信息

void QWGraphicsView::mouseMoveEvent(QMouseEvent *event)
{QPoint point=event->pos();          //QGraphicsView的坐标emit mouseMovePoint(point);         //发送信号QGraphicsView::mouseMoveEvent(event);
}

//鼠标左键按下事件:

void QWGraphicsView::mousePressEvent(QMouseEvent *event)
{if (event->button()==Qt::LeftButton){QPoint point=event->pos();      //QGraphicsView的坐标emit mouseClicked(point);       //发送信号}QGraphicsView::mousePressEvent(event);
}

//鼠标双击事件:双击我们的控件可以显示该控件的一些信息

void QWGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
{if (event->button()==Qt::LeftButton){QPoint point=event->pos();      //QGraphicsView的坐标emit mouseDoubleClick(point);   //发送信号}QGraphicsView::mouseDoubleClickEvent(event);
}

//按键事件:可以设置对图形操作的删除和移动

void QWGraphicsView::keyPressEvent(QKeyEvent *event)
{emit keyPress(event);    // 发送信号QGraphicsView::keyPressEvent(event);
}

// 当滚轮远离使用者时进行放大,当滚轮向使用者方向旋转时进行缩小

void QWGraphicsView::wheelEvent(QWheelEvent *event)
{if(event->delta() > 0){emit MyWheelEvent("add");// 发送向上滚动信号}else{emit MyWheelEvent("sub");// 发送向下滚动信号}
}

新建GraphicsView、QGraphicsScene层

但我们重构了上面的QGraphicsView类过后接下来我们开始我们的绘制工程制作;
在这里插入图片描述首先我们拖一个GraphicsView控件到我们的画面当中去然后提升为我们继承的类;
在这里插入图片描述然后开始定义我们需要用到的sence层和我们item需要存储数据的key,这里item存储数据用的应该是一个map类型,一个key对应一个数据,下面我定义了一个枚举分别对应存储ID的key和中文文字的数据key,然后还定义了两个变量一个用来存储当前item个数的ItemNum,我们在新建一个Item的时候可以将这个数值作为自加操作并赋给ID的key中作为保存,

	enum{ITEMID = 1, // IDkeyITEMDATA	// dataKey};QGraphicsScene *scene; // item管理图层int seqNum=0;				// ID个数int layers;				// 图层层数

然后我们在主页面设置view的属性和绑定我们的scene图层

	scene=new QGraphicsScene(-300,-200,600,200); //创建QGraphicsSceneui->View->setScene(scene);              //与view关联ui->View->setCursor(Qt::CrossCursor);   //设置鼠标ui->View->setMouseTracking(true);       //鼠標捕獲ui->View->setDragMode(QGraphicsView::RubberBandDrag); // 設置拖動模式

到这里我们的图层就构建好了下面就开始绘制我们的第一个item图形

绘制Item图形控件

绘制圆形

// 可以通过调整这个属性得到不同的图形,例如椭圆QGraphicsEllipseItem   *item=new QGraphicsEllipseItem(-50,-50,100,60);item->setFlags(QGraphicsItem::ItemIsMovable 
/*该项支持使用鼠标进行交互式移动。通过单击项目然后拖动,项目将与鼠标光标一起移动。如果项目具有子项,则也会移动所有子项。如果项目是选定内容的一部分,则所有选定项目也将被移动。此功能是通过QGraphicsItem的鼠标事件处理程序的基本实现提供的。 */| QGraphicsItem::ItemIsSelectable 
/*该项支持选择。启用此功能将启用setSelected()来切换项目的选择。它还允许在调用QGraphicscene::setSelectionArea()时,通过单击项目或使用QGraphicsView中的橡皮筋选择,自动选择项目。*/ | QGraphicsItem::ItemIsFocusable);
/*该项支持键盘输入焦点(即,它是一个输入项)。启用此标志将允许项目接受焦点,这再次允许将关键事件传递到QGraphicsItem::keyPressEvent()和QGraphicsItem::keyReleaseEvent()。*/
// 更多的设置选项可以通过F1进去查看更多item->setBrush(QBrush(Qt::cyan)); // 设置笔刷颜色item->setPos(-50+(qrand() % 100),-50+(qrand() % 100)); // 这里设置item的放置位置这里随机放置到中心坐标点附近-50,50的坐标点item->setZValue(++layers);item->setData(ITEMID,++seqNum);item->setData(ITEMDATA,"圆形");scene->addItem(item);scene->clearSelection();item->setSelected(true);

绘制矩形

    QGraphicsRectItem   *item=new QGraphicsRectItem(-50,-25,100,50);item->setFlags(QGraphicsItem::ItemIsMovable| QGraphicsItem::ItemIsSelectable| QGraphicsItem::ItemIsFocusable);item->setBrush(QBrush(Qt::yellow));item->setPos(-50+(qrand() % 100),-50+(qrand() % 100));item->setZValue(++layers);item->setData(ITEMID,++seqNum);item->setData(ITEMDATA,"矩形");scene->addItem(item);scene->clearSelection();item->setSelected(true);

绘制三角形

    QGraphicsPolygonItem   *item=new QGraphicsPolygonItem;QPolygonF   points;points.append(QPointF(0,-40));points.append(QPointF(60,40));points.append(QPointF(-60,40));item->setPolygon(points);item->setPos(-50+(qrand() % 100),-50+(qrand() % 100));item->setFlags(QGraphicsItem::ItemIsMovable| QGraphicsItem::ItemIsSelectable| QGraphicsItem::ItemIsFocusable);item->setBrush(QBrush(Qt::magenta));item->setZValue(++layers);item->setData(ITEMID,++seqNum);item->setData(ITEMDATA,"三角形");scene->addItem(item);scene->clearSelection();item->setSelected(true);

绘制文字

 //添加文字QString str=QInputDialog::getText(this,"输入文字","请输入文字");if (str.isEmpty())return;QGraphicsTextItem   *item=new QGraphicsTextItem(str);QFont   font=this->font();font.setPointSize(20);font.setBold(true);item->setFont(font);item->setFlags(QGraphicsItem::ItemIsMovable| QGraphicsItem::ItemIsSelectable| QGraphicsItem::ItemIsFocusable);item->setPos(-50+(qrand() % 100),-50+(qrand() % 100));item->setZValue(++layers);item->setData(ITEMID,++seqNum);item->setData(ITEMDATA,"文字");scene->addItem(item);scene->clearSelection();item->setSelected(true);

绘制直线

    QGraphicsLineItem   *item=new QGraphicsLineItem(-100,0,100,0);item->setFlags(QGraphicsItem::ItemIsMovable| QGraphicsItem::ItemIsSelectable| QGraphicsItem::ItemIsFocusable);QPen    pen(Qt::red);pen.setWidth(3);item->setPen(pen);item->setZValue(++frontZ);item->setPos(-50+(qrand() % 100),-50+(qrand() % 100));item->setZValue(++layers);item->setData(ITEMID,++seqNum);item->setData(ITEMDATA,"直线");scene->addItem(item);scene->clearSelection();item->setSelected(true);

学会了以上的几种绘图方式其实就已经可以做很多事情了下面扩展几种控件的操作

组合、打散、前置和后置

组合

具体的实现方法是引入一个QGraphicsItemGroup类将选中的控件添加到组中然后关闭每一个单独的item的选择、焦点、功能,然后将group加入到view中显示,而打散就是将group中的item全部取出来解除组合。

    int cnt=scene->selectedItems().count();if (cnt>1){QGraphicsItemGroup* group =new QGraphicsItemGroup; //创建组合scene->addItem(group); //组合添加到场景中for (int i=0;i<cnt;i++){QGraphicsItem* item=scene->selectedItems().at(0);item->setSelected(false); //清除选择虚线框item->clearFocus();group->addToGroup(item); //添加到组合}group->setFlags(QGraphicsItem::ItemIsMovable| QGraphicsItem::ItemIsSelectable| QGraphicsItem::ItemIsFocusable);group->setZValue(++layers);scene->clearSelection();group->setSelected(true);}

打散

int cnt=scene->selectedItems().count();if (cnt==1){QGraphicsItemGroup  *group;group=(QGraphicsItemGroup*)scene->selectedItems().at(0);scene->destroyItemGroup(group);}

控件前置

这里我们只需要通过setZValue接口设置当前层数就可以实现效果。

    int cnt=scene->selectedItems().count();if (cnt>0){ QGraphicsItem* item=scene->selectedItems().at(0);//获取选中的第一个itemitem->setZValue(++layers);}

控件后置

    int cnt=scene->selectedItems().count();if (cnt>0){QGraphicsItem* item=scene->selectedItems().at(0);item->setZValue(0);}

完成了这些功能过后我们把前面的鼠标、按键和滚轮时间结合起来

绑定功能事件

在这个连接信号中我设置了选中item按下delete删除选中的控件,需要注意的是删除多个控件的时候遍历控件的时候每次信号进来scene->selectedItems().count()函数中的数值都会发生改变所以每次删除对的时候我们都删除选中的低at(0)的控件;
按键上下左右这里制作了移动单个item控件还需要做更改,这里用到了 item的设置坐标接口setX和setY也就是设置item的坐标,这里利用item的xy坐标信息进行加减就可以实现坐标的移动移动的幅度大小根据自己需求设计即可;
对于空格这里用来设置item控件的角度,item同样提供了一个角度接口setRotation这里也是将获取item当前的角度值然后进行加减操作就可以实现角度的变化了。

/* 鍵盤按鍵監控 */connect(ui->View,&QWGraphicsView::keyPress,this,[=](QKeyEvent *event){do {QGraphicsItem   *item;int scencSelectCount = scene->selectedItems().count();qDebug() << scene->selectedItems().count() <<endl;if(Qt::Key_Delete == event->key() && scencSelectCount>=1){for (int i = 0;i < scencSelectCount;i++) {item=scene->selectedItems().at(0);//每次都删除第一个scene->removeItem(item);}break;}if (scencSelectCount!=1)break; //没有选中的绘图项,或选中的多于1个item=scene->selectedItems().at(0);if(Qt::Key_Left == event->key()){item->setX(-1+item->x()); //左移break;}if(Qt::Key_Right == event->key()){item->setX(1+item->x());//右移break;}if(Qt::Key_Up == event->key()){item->setY(-1+item->y());//上移break;}if(Qt::Key_Down == event->key()){item->setY(1+item->y());//下移break;}if(Qt::Key_Space == event->key()){item->setRotation(90+item->rotation());//旋转90度break;}} while (false);});

这里监控鼠标的滚动,但我们选择的控件只有一个的时候(用selectedItems().count()判断)判断鼠标滚轮方向然后利用item提供的scale参数也就是大小然后按照百分比的方式去叠加来实现item的放大和缩小。

 /* 鼠标滚轮事件 */connect(ui->View,&QWGraphicsView::MyWheelEvent,this,[=](QString str){if (scene->selectedItems().count()!=1)return; //没有选中的绘图项,或选中的多于1个QGraphicsItem   *item=scene->selectedItems().at(0);if (str == "add"){item->setScale(0.1+item->scale());//放大}else{item->setScale(-0.1+item->scale());//缩小}});

这里监控鼠标的移动事件,这个信号发送过来的数据是一个QPoint 他带的坐标是指的是我们view层的坐标信息他是以左上方为中心点,而我们的scene的坐标是已中心为坐标轴中心
在这里插入图片描述蓝色的交叉是view的0,0,红色的交叉点是sence的0,0;

/* 鼠標移動事件 用於獲取坐標 */connect(ui->View,&QWGraphicsView::mouseMovePoint,this,[=](QPoint point){QPointF pointScene=ui->View->mapToScene(point); //转换到Scene坐标ui->label->setText(QString::asprintf("View 坐标:%d,%d  Scene 坐标:%.0f,%.0f",                                           point.x(),point.y(),pointScene.x(),pointScene.y()));});

但鼠标左键按下的时候传来一个坐标位置,然后我们将这个坐标位置转换为sence坐标,然后再sence图层去寻找这个坐标有没有item控件,这里新建了一个空的item用来接受这个查找的返回结果,如果返回不为空我们可以显示这个item的坐标信息以及图标类型,还有我们给这个item设置的data属性,这个也是根据需求来指定,如果选择的位置为空我们可以做一个标志如果这里按下了绘画按钮,这里可以进行一个item的绘画操作。

/* 鼠標左擊事件 */connect(ui->View,&QWGraphicsView::mouseClicked,this,[=](QPoint point){QPointF pointScene=ui->View->mapToScene(point);         //转换到Scene坐标QGraphicsItem  *item=NULL;item=scene->itemAt(pointScene,ui->View->transform());   //获取光标下的绘图项if (item != NULL) //有绘图项{QPointF pointItem=item->mapFromScene(pointScene);   //转换为绘图项的局部坐标ui->label_2->setText(QString::asprintf("Item坐標:%.0f,%.0f  選中圖標ID:%1 圖標類型:%2",pointItem.x(),pointItem.y()).arg(item->data(ItemId).toString()).arg(item->data(ItemDesciption).toString()));}else if(yuanFlag){ //判断是否有绘画标志位QGraphicsEllipseItem   *item=new QGraphicsEllipseItem(-50,-50,100,100);item->setFlags(QGraphicsItem::ItemIsMovable| QGraphicsItem::ItemIsSelectable| QGraphicsItem::ItemIsFocusable);item->setBrush(QBrush(Qt::cyan));item->setPos((pointScene.x()+10),(pointScene.y()+10));item->setData(ITEAID,++seqNum);item->setData(ITENDATA,"圆形");scene->addItem(item);scene->clearSelection();item->setSelected(true);yuanFlag = false;}});

双击信号这里暂时没有写有需求的功能

/* 鼠標雙擊事件 */connect(ui->View,&QWGraphicsView::mouseDoubleClick,this,[=](){});

总结

在这里插入图片描述

这篇文章也只是简单的介绍了GraphicsView的基本操作,熟练掌握这个类的使用还可以做很多好玩有趣的程序,在这个互联网如此发达的时代好好利用网络上的知识来丰富自己,也让自己所踩的坑通过分享让大家一起进步。
编程这回事,乃漫长之事,我不能用冰山一角衡量冰山之高,不能用燕雀心境描绘鸿鹄之志。只希望洁身自好,努力追求,愿为燕雀找寻星空。

参考博文:
QPainter和QGraphicsView的区别
Qt5.9 Graphics View 最简单制作画图
程序例子 提取码:lloh
GraphicsViewDemo 阿里云个人代码demo


http://chatgpt.dhexx.cn/article/ifEA2jRo.shtml

相关文章

Qt 绘图之QGraphicsScene QGraphicsView QGraphicsItem详解

Graphics View提供了一个界面&#xff0c;它既可以管理大数量的定制2D graphical items&#xff0c;又可与它们交互&#xff0c;有一个view widget可以把这些项绘制出来&#xff0c;并支持旋转与缩放。这个柜架也包含一个事件传播结构&#xff0c;对于在scene中的这些items,它具…

PyQt5:QGraphicsScene入门一:基本介绍、场景定义、添加元素

为什么80%的码农都做不了架构师?>>> 简介说明: 这个QGraphicsScene类用于在场景中操作大量的2D图形元素,这个类是作为一个容器QGraphicsItems存在的,它是连同QGraphicsView用于可视化的二维表面的图形项目,如直线,矩形,文本,甚至定制物品;还可以有效地…

QGraphicsView,QGraphicsScene和QGraphicsItem

图形视图框架提供了一个基于图形项的模型视图编程方法&#xff0c;主要由场景、视图和图形项三部分组成&#xff0c;这三部分分别由QGraphicsScene、QGraphicsView和QGraphicsItem这三个类来表示。 场景QGraphicsScene QGraphicsScene类提供绘图场景&#xff08;Scene&#…

Qt图形视图框架:QGraphicsScene详解

一、描述 1、场景提供了一个用于管理大量2D图形项的平面。该类充当图形项的容器。 它与视图一起用于可视化2D曲面上的图形图形项。 2、场景没有自己的视觉外观&#xff0c;只负责管理图形项。 3、场景的最大优势之一就是其快速有效地定位图形项的能力。即使场景中有数百万个…

Qt开发技术:图形视图框架(二)场景QGraphicsScene、QGraphicsItem与QGraphicsView详解

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/117660217 长期持续带来更多项目与技术分享&#xff0c;咨询请加QQ:21497936、微信&#xff1a;yangsir198808 红胖子(红模仿)的博文大全&#xff1…

TLS、SSL原理解析

TLS、SSL https协议就是建立在TLS、SSL之上的。

SSL证书原理讲解

SSL证书原理讲解 - 2240930501 - 博客园一直以来都对数字证书的签发&#xff0c;以及信任等事情一知半解。总算有个闲适的周末来总结和深入一下相关的知识。 CA: CA(Certificate Authority)是证书的签发机构&#xff0c;它是负责管理和签发证书的https://www.cnblogs.com/dingl…

浅谈SSL/TLS工作原理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 浅谈SSL/TLS工作原理 SSL对称加密非对称加密定义工作过程特点及性能分析非对称加密常用算法举例 非对称加密和对称加密各自有啥优缺点&#xff1f;CA&#xff08;Certificate…

SSL工作原理介绍以及java实现

SSL工作原理介绍以及java实现 目录 SSL工作原理介绍以及java实现 SSL简介SSL工作原理 握手协议Handshake protocol 1握手阶段使用RSA加密算法2握手阶段使用Diffie-Hellman加密算法记录协议Record protocol警报协议Alert protocolWireshark抓包图解java实现Secure Sockets Laye…

SSL证书原理是什么?ssl证书工作流程是什么

SSL证书的运用促使网址更加安全性&#xff0c;做为一种加密传输协议书技术性。SSL的挥手协议书让顾客和集群服务器进行彼此之间的身份验证。为了让各位能进一步了解ssl证书&#xff0c;小编来向各位介绍SSL证书原理。 SSL证书原理如下&#xff1a; ①手机客户端向网络服务器恳…

SSL 工作原理

博客引用处&#xff08;以下内容在原有博客基础上进行补充或更改&#xff0c;谢谢这些大牛的博客指导&#xff09;&#xff1a; SSL工作原理 首先说明下SSL工作原理&#xff1a; 1.1 产生背景 基于万维网的电子商务和网上银行等新兴应用&#xff0c;极大地方便了人们的日常生活…

SSL原理介绍

SSL原理介绍 SSL——安全套接字层&#xff08;Secure Sockers Layer&#xff09;协议由著名的Netscape公司开发。为了保证通信双方建立安全可靠的传输隧道&#xff0c;SSL使用PKI中的数字证书技术对通信双方进行身份认证&#xff1b;使用对称加密来保证数据保密性&#xff1b;使…

ssl 原理和建立连接过程

ssl 与http关系 ssl (“Secure Sockets Layer”)加密原理 和https的关系 https http ssl ssl 位置&#xff1a; SSL握手 证书主要作用是在SSL握手中&#xff0c;我们来看一下SSL的握手过程 客户端提交https请求服务器响应客户&#xff0c;并把证书公钥发给客户端客户端验…

SSL/TLS 的工作原理

HTTPS 之所以能达到较高的安全性要求,就是结合了 SSL/TLS 和 TCP 协议,对通信数据进行加密,解决了 HTTP 数据透明的问题。接下来重点介绍一下 SSL/TLS 的工作原理。 SSL 和 TLS 的区别? SSL 和 TLS 没有太大的区别。 SSL 指安全套接字协议(Secure Sockets Layer),首次…

SSL工作原理

公钥和私钥 一直以来对公钥和私钥都理解得不是很透彻&#xff0c;感觉到模棱两可。今天在网上找了半天&#xff0c;通过查看对这个密钥对的理解&#xff0c;总算弄清楚了。 公钥和私钥就是俗称的不对称加密方式&#xff0c;是从以前的对称加密&#xff08;使用用户名与…

SSL技术原理

SSL详解 建议直接看这&#xff1a;https://cshihong.github.io/2019/05/11/SSL-VPN%E6%8A%80%E6%9C%AF%E5%8E%9F%E7%90%86/ SSL [虚拟专用网络]的技术主要用到了SSL技术。有关SSL具体技术&#xff0c;可以参考&#xff1a; SSL/TLS协议详解 SSL [虚拟专用网络]简介 SSL [虚拟专…

SSL协议原理详解

SSL 可参考&#xff1a;SSL技术原理 SSL简介 SSL和TLS&#xff1a; SSL (Secure Sockets Layer&#xff09;安全套接层。是由Netscape公司于1990年开发&#xff0c;用于保障Word Wide Web&#xff08;WWW&#xff09;通讯的安全。主要任务是提供私密性&#xff0c;信息完整性…

SSL协议原理

文章目录 SSL协议原理SSL协议结构SSL原理&#xff08;握手协议&#xff09;SSL握手协议第一阶段客户端Client Hello数据包服务端server Hello数据包 SSL握手协议第二阶段**Certificate消息数据包**Server Key Exchange消息数据包ServerHello Done数据包 SSL握手协议第三阶段Cli…

关于SSL原理的详解

关于SSL原理的详解 SSL原理详解一、SSL是什么&#xff1f;二、建立SSL通道过程1.简化篇2.具体建立过程 总结 SSL原理详解 其实SSL从网上看到的资料很多了&#xff0c;但是发现还是没有将原理讲得特别清楚&#xff0c;尤其是对CA&#xff0c;433端口与80端口的数据传输原理&…

ExpandableListView--基本使用介绍

1 什么是ExpandableListView&#xff1f;有啥作用? 首先看一张ExpandableListView 的继承关系图&#xff1a; ExpandableListView的继承关系 根据上图可知&#xff0c;ExpandableListView是ListView的子类。而expandable 在英文中的意思是可扩展的&#xff0c;所以ExpandableL…