0


QGraphicsView图形视图框架使用(二)图形交互

文章目录

在开发基于图形视图框架QGraphicsView的应用的时候,其中很重要的一部分工作就是处理与框架中图元的交互。这也是最让人头疼的。这里就介绍一下与Item交互过程中那些常见的操作。

标准图元

在QGraphicsView图形视图框架中QT提供了很多标准的Item,通过组合使用各种基本图元,我们可以实现各种各样的复杂场景。充分的了解和熟悉标准图元,能避免在开发的过程中重复造轮子。QGraphicsView中标准图元如下表所示:
图元名称说明QGraphicsLineItem用来绘制直线,可以通过setLine(const QLineF&)来添加。QGraphicsRectItem用来绘制矩形,通过setRect()来进行添加QGraphicsEllipseItem用来绘制椭圆,或者部分椭圆。通过设置setStartAngle(int)和setSpanAngle(int)可以绘制椭圆的一部分。设置的值是1度的1/16。QGraphicsPolygonItem用来绘制多边形,通过setPolygon()添加QGraphicsPathItem绘制一个路径,通过setPath()来进行添加QGraphicsSimpleTextItem绘制简单文本,除了可以设置字体以外,不支持其它的富文本样式QGraphicsTextItem绘制格式化的文本,可以通过setHtml()或者setDocument()设置html,还可以添加有交互内容的URL超链接。QGraphicsPixmapItem绘制图片,或者渲染一个图片QGraphicsProxyWidget绘制任意的QWdiget控件,视图框架允许我们与添加的控件进行交互。
在使用标准图元的时候有几点需要注意:
1.可以通过设置画笔(setPen())来修改边线的样式和颜色,可以通过设置画刷(setBrush())来修改填充的内容的颜色和样式。
2.QGraphicsTextItem不支持设置画刷和画笔,我们可以通过setDefaultTextColor()设置文本颜色,或者通过HTML样式来实现。
3.尽量使用QGraphicsSimpleTextItem而不是QGraphicsTextItem,因为为了支持HTML解析和渲染,QGraphicsTextItem引入了一个轻量级的HTML引擎,会对性能产生损耗。
标准控件的绘制调用方法如下:

#pragmaexecution_character_set("utf-8")#include"mainwindow.h"#include<QApplication>#include<QGraphicsView>#include<QGraphicsItem>#include<QTransform>#include<QLabel>#include<QPushButton>#include<QGraphicsProxyWidget>intmain(int argc,char*argv[]){
    QApplication a(argc, argv);
    QGraphicsScene scene;//在Scene中心添加一个十字坐标
    scene.addLine(-200,0,200,0);
    scene.addLine(0,-200,0,200);//添加矩形图元
    QGraphicsRectItem* rect_item = scene.addRect(-50,-50,150,150);
    rect_item->setBrush(QBrush(QColor("#4D9CF8")));//添加椭圆图元
    QGraphicsEllipseItem* ellipseItem = scene.addEllipse(QRectF(QPointF(-50,100),QPointF(50,50)),QPen("#0000FF"),QBrush(QColor("#4D00F8")));
    ellipseItem->setZValue(10);//添加多边形
    QPolygonF polygon;
    polygon <<QPointF(-30,-30)<<QPointF(-30,40)<<QPointF(20,30)<<QPointF(0,0);
    scene.addPolygon(polygon,QPen(),QBrush(QColor("#FF0000")));//绘制文本
    QGraphicsTextItem* text_item = scene.addText(QString("测试文本ABC"),QFont("Micros"));
    text_item->setPos(-30,-100);//绘制路径
    QPainterPath path;
    path.moveTo(-300,-50);
    path.lineTo(0,-150);
    path.lineTo(200,0);
    QGraphicsPathItem* path_item = scene.addPath(path,QPen(QColor("#00FF00")));//绘制图片
    QGraphicsPixmapItem* pixmap_item = scene.addPixmap(QPixmap(":/demo.png"));
    pixmap_item->setPos(-300,-50);
    pixmap_item->setZValue(20);//添加自定义控件
    QPushButton* button =newQPushButton("按钮");
    QGraphicsProxyWidget* button_item = scene.addWidget(button);
    button_item->setPos(100,30);
    QGraphicsView view(&scene);
    view.show();return a.exec();}

显示效果如下:
在这里插入图片描述

图元优化

默认配置下,图形视图框架是没有优化绘制的,绘制的图形和直线毛边非常严重,不顺滑。我们可以通过开启渲染的抗锯齿操作来优化渲染。对应的配置如下:

QGraphicsView view(&scene);
view.setRenderHint(QPainter::Antialiasing);
view.show();

开起了抗锯齿之后,渲染效果会好很多,显示效果如下:
在这里插入图片描述
开启抗锯齿效果之后,有时候会出现一些非常诡异的现象,就是相同宽度的线有些线看上去比别的线粗一些。这是因为有的线位于两个图像像素之间,在开启抗锯齿进行插值的时候,相邻的两个线都被渲染了。我们可以通过偏移半个像素来解决这个问题:

QRectF rect(-width /2,-height /2, width, height);
rect.translate(0.5,0.5);

除了偏移像素外,在绘制水平线和垂直线的时候,我们也可以通过关闭抗锯齿效果来解决这个问题。除了对整个视图进行抗锯齿操作之外,我们还可以单独对文字或者图片进行优化。对应的配置如下:

QGraphicsView view(&scene);//抗锯齿效果
view.setRenderHint(QPainter::Antialiasing);//绘制文本的时候抗锯齿
view.setRenderHint(QPainter::TextAntialiasing);//平滑的图片变换
view.setRenderHint(QPainter::SmoothPixmapTransform);
view.show();

虽然抗锯齿效果能提升图像质量,但这都是以牺牲性能为代价的,在实际使用的时候还是要根据需要开启,不要盲目的使用,防止对性能产生损耗。

图元选择

添加到Scene中的Item,默认是不支持选择的,我们需要通过设置对应的标志位来开启选择属性。

item->setFlag(QGraphicsItem::ItemIsSelectable,true);

开启选择属性之后,我们可以通过鼠标左键来选择图元,同时配合Ctrl键我们可以同时选中多个图元。对应的调用方法如下:

#pragmaexecution_character_set("utf-8")#include"mainwindow.h"#include<QApplication>#include<QGraphicsView>#include<QGraphicsItem>#include<QTransform>#include<QLabel>#include<QPushButton>#include<QGraphicsProxyWidget>intmain(int argc,char*argv[]){
    QApplication a(argc, argv);
    QGraphicsScene scene;//添加矩形图元
    QGraphicsRectItem* rect_item = scene.addRect(-50,-50,100,100);
    rect_item->setBrush(QBrush(QColor("#4D9CF8")));
    rect_item->setFlag(QGraphicsItem::ItemIsSelectable,true);//通过渐变色填充图元
    QGraphicsRectItem* gradient_rect_item = scene.addRect(60,-50,100,100);
    QLinearGradient gradient(0,0,100,100);
    gradient.setColorAt(0, Qt::yellow);
    gradient.setColorAt(0.5, Qt::red);
    gradient.setColorAt(1.0, Qt::magenta);
    QBrush brush = gradient;
    gradient_rect_item->setBrush(brush);
    gradient_rect_item->setFlag(QGraphicsItem::ItemIsSelectable,true);

    QGraphicsView view(&scene);//抗锯齿效果
    view.setRenderHint(QPainter::Antialiasing);
    view.show();return a.exec();}

被选中的图元,边框线会变成虚线,效果如下:
在这里插入图片描述
通过对视图View进行如下配置,可以开启视图的框选模式,框选模式可以通过鼠标进行范围选择。

view.setDragMode(QGraphicsView::RubberBandDrag);

显示效果如下:
在这里插入图片描述
除了RubberBandDrag模式外,QGraphicsView还支持ScrollHandDrag,设置了该效果之后,我们可以通过鼠标左键对整个场景进行拖拽移动。

view.setDragMode(QGraphicsView::ScrollHandDrag);

显示效果如下所示:
在这里插入图片描述
除了上面的选择方式之外,图形视图框架中还提供了一些与选择图元有关的函数接口。我们可以通过调用对应的接口选中/取消选中某些图元。

//选中或取消选中某个图元QGraphicsItem::setSelected(true/false)//判断某个图元是否被选中了QGraphicsItem::isSelected()//设定选中范围,范围内的图元都会被选中QGraphicsScene::setSelectionArea()//取消Scene中选中的图元QGraphicsScene::clearSelection()//获取Scene中被选择图元的列表QGraphicsScene::selectedItems()

除了选择属性之外,默认添加的图元也是不支持移动的,我们也可以通过配置对应的属性开启图元的移动属性,对应的配置如下:

intmain(int argc,char*argv[]){
    QApplication a(argc, argv);
    QGraphicsScene scene;//添加矩形图元
    QGraphicsRectItem* rect_item = scene.addRect(-50,-50,100,100);
    rect_item->setBrush(QBrush(QColor("#4D9CF8")));//添加移动属性
    rect_item->setFlag(QGraphicsItem::ItemIsMovable,true);
    QGraphicsView view(&scene);//抗锯齿效果
    view.setRenderHint(QPainter::Antialiasing);
    view.show();return a.exec();}

开启了移动开关之后,我们就可以自由的拖动添加的图元了对应的效果如下:
在这里插入图片描述

图元焦点

为了让图元响应键盘事件,我们需要对图元的焦点进行处理。Scene中某一时刻只允许一个Item有焦点,接受到的键盘事件会被发送到对应有焦点的Item。为了让图元响应焦点事件,我们需要开启图元的焦点属性,对应的设置如下:

item1->setFlag(QGraphicsItem::ItemIsFocusable,true);

和图元的选择一样,针对焦点图元的处理,图形框架也提供了一系列的接口,如下:

//设置图元焦点(鼠标点击也可以)QGraphicsItem::setFocus()//判断某个图元是否有焦点QGraphicsItem::hasFocus()//清除某个图元的焦点(也可以通过点击Scene背景实现)QGraphicsItem::clearFocus()//让某个图元获得焦点QGraphicsScene::setFocusItem()//获得有焦点的图元QGraphicsScene::focusItem()//设置了StickyFocus之后便不可以通过点击Scene背景来取消焦点了QGraphicsScene::setStickyFocus(true);

图元层次

默认添加的图元的Z值都是相同的都是0,这时候的前后显示关系跟添加的先后顺序有关,后添加的图元显示在之前添加的图元的前面。我们可以通过设置图元的Z值,来调整图元的层次关系,z值越大显示的层次越高,z值越小显示的层次越低,对应的使用方法如下:

intmain(int argc,char*argv[]){
    QApplication a(argc, argv);
    QGraphicsScene scene;
    QGraphicsEllipseItem *item1 = scene.addEllipse(0,0,100,50);
    item1->setBrush(Qt::red);
    item1->setZValue(-20);
    
    QGraphicsEllipseItem *item2 = scene.addEllipse(50,0,100,50);
    item2->setBrush(Qt::green);
    item2->setZValue(10);
    
    QGraphicsEllipseItem *item3 = scene.addEllipse(0,25,100,50);
    item3->setBrush(Qt::blue);
    item3->setZValue(-40);
    
    QGraphicsEllipseItem *item4 = scene.addEllipse(50,25,100,50);
    item4->setBrush(Qt::gray);
    item4->setZValue(20);

    QGraphicsView view(&scene);//抗锯齿效果
    view.setRenderHint(QPainter::Antialiasing);
    view.show();return a.exec();}

显示效果如下:
在这里插入图片描述
对包含子元素的组合对象来说,子对象的层次关系,由父对象确定,如果一个父对象显示在另个图元的前面,它的子对象也显示在另一个图元的前面。


本文转载自: https://blog.csdn.net/yang1fei2/article/details/125694709
版权归原作者 码农飞飞 所有, 如有侵权,请联系我们删除。

“QGraphicsView图形视图框架使用(二)图形交互”的评论:

还没有评论