在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引擎,会对性能产生损耗。
标准控件的绘制调用方法如下:
#pragma execution_character_set("utf-8")
#include "mainwindow.h"
#include
#include
#include
#include
#include
#include
#include
int main(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 = new QPushButton("按钮");
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键我们可以同时选中多个图元。对应的调用方法如下:
#pragma execution_character_set("utf-8")
#include "mainwindow.h"
#include
#include
#include
#include
#include
#include
#include
int main(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()
除了选择属性之外,默认添加的图元也是不支持移动的,我们也可以通过配置对应的属性开启图元的移动属性,对应的配置如下:
int main(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值越小显示的层次越低,对应的使用方法如下:
int main(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();
}
显示效果如下:
对包含子元素的组合对象来说,子对象的层次关系,由父对象确定,如果一个父对象显示在另个图元的前面,它的子对象也显示在另一个图元的前面。