绘图
Qt
的二维绘图基本功能是使用QPainter
在绘图设备上绘图
绘图设备包括QWidget, QPixmap
等
Qt
还提供了Graphics View
架构
使用QGraphicsView,QGraphicsScene
,和各种QGraphicsItem
类绘图
且每个图件是可选择,可交互的
Graphics View
架构为绘制复杂组件化图形提供了便利
QPainter基本绘图
QPainter绘图系统
- QPainter
与QPaintDevice
Qt
的绘图系统使用户可在屏幕或打印设备上用相同的Api
绘图,
绘图系统基于QPainter, QPaintDevice
和QPaintEngine
类
QPaintDevice
是一个可使用QPaint
进行绘图的抽象的二维界面
QPaintEngine
给QPainter
提供在不同设备上绘图的接口
QPaintEngine
类由QPainter
和QPaintDevice
内部使用
一般的绘图设备包括QWidget, QPixmap, QImage
等
这些绘图设备为QPainter
提供一个画布
- paintEvent
事件和绘图区
QWidget
类及其子类是最常用的绘图设备
从QWidget
类继承的类都有paintEvent()
事件,要在设备上绘图,只需重定义此事件并编写响应代码
创建一个QPainter
对象获取绘图设备接口,就可在绘图设备的画布上绘图了
void x::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
...
}
绘图区的宽度由QWidget::width()
获取
高度由QWidget::height()
获取
视口坐标[viewport
]
逻辑坐标/
窗口坐标
QPainter绘图的主要属性
绘制基本图形元素:点,直线,圆形, 矩形,曲线,文字等
控制这些绘图元素特性的主要是QPainter
的3
个属性,分别是:
- pen
属性,
是一个QPen
对象,用于控制线条的颜色,宽度,线型等
- brush
属性
是一个QBrush
对象,用于设置一个区域的填充特性,可设置填充颜色,填充方式,渐变特性等
还可采用图片作材质填充
- font
属性
是一个QFont
对象,用于绘制文字时,设置文字的字体样式,大小等属性
创建实例
Q_DECL_OVERRIDE
宏,表示函数是对父类虚函数的重载
对QWidget
支持void x::paintEvent(QPaintEvent*),int width(),int height()
对QRect,QPen
支持void setWidth(...),void setColor(...),void setStyle(...),void setCapStyle(...),void setJoinStyle(..)
对QPainter
支持void setRenderHint(...),void setPen(...),void setBrush(...),void drawRect(...)
对QBrush
支持void setColor(...),void setStyle(...)
QPen的主要功能
QPen
的主要函数.void setColor(...),void setWidth(...),void setStyle(...),void setCapStyle(...),void setJoinStyle(...)
线条样式
对Qt::SolidLine,Qt::DashLine,Qt::DotLine,Qt::DashDotLine,Qt::DashDotDotLine,Qt::CustomDashLine
线条端点样式
对Qt::SquareCap,Qt::FlatCap,Qt::RoundCap
线条连接样式
对Qt::BeveJoin,Qt::MiterJoin,Qt::RoundJoin
QBrush的主要功能
QBrush
的主要函数.void setColor(...),void setStyle(...),void setTexture(...),void setTextureImage(...)
枚举类型Qt::BrushStyle
如Qt::NoBrush,Qt::SolidPattern,Qt::HorPattern,Qt::VerPattern,Qt::LinearGradientPattern,Qt::RadialGradientPattern,Qt::ConicalGradientPattern,Qt::TexturePattern
渐变填充
使用渐变填充需要用渐变类的对象作为Painter
的brush
有3
个实现渐变填充的类
-对QLinearGradient
线性渐变
-对QRadialGradient
简单辐射渐变,扩展辐射渐变
-对QConicalGradient
圆锥形渐变
三个类均继承自QGradient
对QGradient
支持void setSpread(...)
-对PadSpread
-对RepeatSpread
-对ReflectSpread
QPainter绘制基本图形元件
基本图形元件
QPainter
绘制基本图形元件的函数
如,drawArc,drawChord,drawConvexPolygon,drawEllipse,drawImage,drawLine,drawLines,drawPath,drawPie,drawPixmap,drawPoint,drawPoints,drawPolygon,drawPolyline,drawRect,drawRoundedRect,drawText,,eraseRect,fillPath,fillRect
QPainterPath的使用
QPainterPath
是一系列绘图操作的顺序集合,便于重复使用
一个PainterPath
由许多基本的绘图操作组成,
一个闭合的PainterPath
是终点和起点连接起来的绘图路径
坐标系统和坐标变换
坐标变换函数
QPainter
在窗口上绘图的默认坐标系统,称为绘图设备的物理坐标
通过变换,基于物理坐标得到逻辑坐标或相反
QPainter
有关坐标变换操作的函数
对坐标变换,支持void translate(...),void rotate(...),void scale(...),void shear(...)
对状态保存与恢复,支持void save(),void restore(),void resetTransform()
QTransform
直接应用变换矩阵,更灵活
坐标平移
支持void translate(qreal x, qreal y)
实现像素移动
坐标旋转
支持void rotate(qreal)
缩放
void scale(qreal, qreal)
// 横向,纵向缩放比例
状态保存与恢复
坐标变换绘图实例
绘制3个五角星的程序
对QPainterPath
支持void moveTo(...),void lineTo(...),void closeSubpath(),void addText(...)
绘制五角星的PainterPath的定义
视口和窗口
视图和窗口的定义与原理
绘图设备的物理坐标是基本的坐标系
通过QPainter
的平移,旋转等变换可得到更多更易操作的逻辑坐标
为实现更方便的坐标,QPainter
还提供了视口,窗口坐标系
// 指定视口原点设备坐标下的位置
// 指定视口宽度,高度
void QPainter::setViewport(int x, int y, int width, int height)
// 窗口左上角逻辑坐标,串口宽度,高度
void QPainter::setWindow(int x, int y, int width, int height)
视口和窗口的使用实例
使用窗口坐标的优点是,只需按窗口坐标定义来绘图,不管实际物理坐标范围大小
对QPainter
支持void drawRect(...),void setViewport(...),void setWindow(...),void setRenderHint(...),void setPen(...),void drawEllipse(...),void rotate(...)
对QPoint,QPen
支持void setWidth(...),void setColor(...),void setStyle(...)
对QRect,QWidget
支持int width(),int height()
绘图叠加的效果
对QPainter
支持void setBrush(...),void setCompositionMode(...)
对QLinearGradient
,支持void setColorAt(...),void setColorAt(...),void setSpread(...)
Graphics View
场景,视图,图形项
在paintEvent()
里的绘图程序,不能实现图元的选择,编辑,拖放,修改等
Qt
为绘制复杂的可交互图形提供了Graphics View
绘图架构,是一种基于图形项的模型/视图模式
使用Graphics View
架构可绘制复杂的有几万个基本图形元件的图形,且每个图形元件是可选择,可拖放,修改的.
Graphics View
架构主要由3
个部分组成:
场景,视图,图形项
场景
QGraphicsScene
类提供绘图场景
场景不可见,是一个抽象的管理图形项的容器
可向场景添加图形项,获取某个图形项等
- 提供管理大量图形项的快速接口
- 将事件传播给每个图形项
- 管理每个图形项的状态,如选择状态,焦点等
- 管理未经变换的渲染功能,主要用于打印
除了图形项
场景还有背景层和前景层,通常由QBrush
指定,
也可通过重新实现drawBackground()
和drawForeground()
函数来实现自定义的背景和前景,实现一些特殊效果
视图
QGraphicsView
提供绘图的视图组件,用于显示场景中的内容
可为一个场景设置几个视图,用于对同一个数据集提供不同的视口
缺省下,当视图大于场景时,
场景在视图的中间部分显示,也可设置视图的Alignment
属性控制场景在视图中的显示位置
当视图小于场景时,视图显示场景一部分内容,可提供滚动显示
视图接收键盘和鼠标输入并转换为场景事件,进行坐标转换后,传送给可视场景.
图形项
图形项是一些基本的图元元件
图形项的基类是QGraphicsItem
Qt
提供了一些基本的图形项,
如绘制椭圆的QGraphicsEllipseItem
绘制矩形的QGraphicsRectItem
绘制文字的QGraphicsTextItem
等
QGraphicsItem
支持如下的一些操作:
- 支持鼠标事件响应
包括鼠标按下,移动,释放,双击,还包括鼠标停留,滚轮,快捷菜单等事件
- 支持键盘输入,按键事件
- 支持拖放操作
- 支持组合,可以是父子项关系组合,也可是通过QGraphicsItemGroup
类进行组合
故,图形项可被选择,拖放,组合,
若编写信号槽函数代码,还可实现各种编辑功能
一个图形项还可包含子图形项,图形项还支持碰撞检测
Graphics View的坐标系统
Graphics View
有三个有效的坐标系,
图形项坐标,场景坐标,视图坐标
场景的坐标等价于QPainter
的逻辑坐标
一般以场景的中心为原点
视图坐标与设备坐标相同,是物理坐标,缺省以左上角为原点
图形项坐标是局部逻辑坐标,一般以图件的中心为原点
图形项坐标
图形项使用自己的局部坐标,
通常以其中心为(0, 0)
也是各种坐标交换的中心
图形项的鼠标事件的坐标是用局部坐标表示的
创建自定义图形项
绘制图形项时只需考虑其局部坐标
QGraphicsScene
和QGraphicsView
会自动进行坐标转换
一个图形项的位置是其中心点在父坐标系统中的坐标
对没有父图形项的图形项,其父对象就是场景,图形项的位置就算在场景中的坐标
如一个图形项还是其他图形项的父项,父项进行坐标变换时,子项也做同样的坐标变换
QGraphicsItem::boundingRect()
是用局部坐标给出的,
但QGraphicsItem::pos()
是仅有的几个例外
它返回的是图形项在父项坐标系中的坐标,如是顶层图形项,就是在场景中的坐标
视图坐标
视图坐标所窗口界面的物理坐标
单位是像素
视图坐标只与widget
或视口有关,
与观察的场景无关
QGraphicsView
视口的左上角坐标总是(0,0)
所有的鼠标事件,拖放事件的坐标先是由视图坐标定义的,用户需要将这些坐标映射为场景坐标
场景坐标
场景是所有图形项的基础坐标
场景坐标描述了每个顶层图形项的位置
创建场景时可定义场景矩形区的坐标范围
QGraphicsScene
,每个图形项在场景里都有一个位置坐标
由函数QGraphicsItem::scenePos()
给出,还有一个图形项边界矩形,由QGraphicsItem::sceneBoundingRect()
函数给出
边界矩形可使QGraphicsScene
知道场景的那个区域发生了变换
场景发生变化时,会发射QGraphicsScene::changed()
信号
参数是一个场景的矩形列表
坐标映射
在场景中操作图形项时,进行场景到图形项,图形项到图形项或视图到场景之间的坐标变换比较有用
在QGraphicsView
的视口上单击鼠标时,通过函数QGraphicsView::mapToScene()
可将视图坐标映射为场景坐标
然后用QGraphicsScene::itemAt()
可获取场景中鼠标光标处的图形项
Graphics View相关的类
Graphics View
结构的主要类包括
视图类QGraphicsView
场景类QGraphicsScene
各种图形项类,图形项类的基类都算QGraphicsItem
- QGraphicsView
类的主要接口函数
QGraphicsView
是用于观察一个场景的物理窗口
场景小于视图时,整个场景视图内可见
场景大于视图时,视图自动提供滚卷条
QGraphicsView
的视口坐标等于显示设备的物理坐标
也可对QGraphicsView
的坐标进行平移,旋转,缩放等变换
QGraphicsView
的主要接口函数
一般的设置函数还有一个对应的读取函数
如setScene()
对应scene()
这里只列设置函数
QGraphicsView
主要函数功能说明
void setScene(...)
void setSceneRect(...)
void setAlignment(...)
void setBackgroundBrush(...)
void setForegroundBrush(...)
void setRenderHints(...)
void setInteractive(...)
QRect rubberBandRect(...)
void setRubberBandSelectionMode(...)
QGraphicsItem* itemAt(...)
QList<QGraphicsItem*> items(...)
QPoint mapFromScene(...)
QPointF mapToScene(...)
QGraphicsScene类的主要接口函数
QGraphicsScene
用于管理图形项的场景,是图形项的容器
有添加,删除图形项的函数
管理图形项的各种函数
QGraphicsScene
主要函数功能说明
void setSceneRect(...)
QGraphicsItemGroup* createItemGroup(...)
void destroyItemGroup(...)
QGraphicsItem* focusItem(...)
void clearFocus(...)
bool hasFocus(...)
void addItem(...)
void removeItem(...)
void clear(...)
QGraphicsItem* mouseGrabberItem(...)
QList<QGraphicsItem*> selectedItems(...)
void clearSelection(...)
QGraphicsItem* itemAt(...)
QList<QGraphicsItem*> items(...)
QGraphicsEllipseItem* addEllipse(...)
QGraphicsLineItem* addLine(...)
QGraphicsPathItem* addPath(...)
QGraphicsPixmapItem* addPixmap(...)
QGraphicsPolygonItem* addPolygon(...)
QGraphicsRectItem* addRect(...)
QGraphicsSimpleTextItem* addSimpleText(...)
QGraphicsTextItem* addText(...)
QGraphicsProxyWidget* addWidget(...)
图形项
QGraphicsItem
是所有图形项的基类
用于可从QGraphicsItem
继承定义自己的图形项
Qt
定义了一些常见的图形项,这些常见的图形项的类的继承关系如图
QGraphicsItem
直接派生了QAbstractGraphicsShapeItem,QGraphicsLineItem,QGraphicsPixmapItem,QGraphicsObject,QGraphicsItemsGroup
QAbstractGraphicsShapeItem
直接派生了QGraphicsEllipseItem,QGraphicsPathItem,QGraphicsPolygonItem,QGraphicsRectItem,QGraphicsSimpleTextItem
QGraphicsObject
直接派生了QGraphicsTextItem
QGraphicsItem
类提供了图形项操作的函数,常见的函数如下
QGraphicsItem
主要函数
void setFlags(...)
void setOpacity(...)
void setGraphicsEffect(...)
void setSelected(...)
void setData(...)
void setX(...)
void setY(...)
void setZValue(...)
void setPos(...)
QPointF scenePos(...)
void resetTransform(...)
void setRotation(...) // 正数表示顺时针旋转
void setScale(...)
QPointF mapFromItem(...)
QPointF mapFromParent(...)
QPointF mapFromScene(...)
QPointF mapToItem(...)
QPointF mapToParent(...)
QPointF mapToScene(...)
常见标志:
QGraphicsItem::ItemIsMovable
QGraphicsItem::ItemIsSelectable
QGraphicsItem::ItemIsFocusable
Graphics View程序基本结构和功能实现
实例程序功能
- 工作区是一个从QGraphicsView
继承得到自定义类QWGraphicsView
作为绘图的视图组件
- 创建一个QGraphicsScene
场景
- 改变窗口大小
视图大于场景时,显示在视图中央
视图小于场景时,视图窗口可滚动显示
- 蓝色椭圆处于场景中间
红色圆形位于场景右下角
- 鼠标在窗口上移动时,
状态栏显示光标的视图坐标,场景坐标
在某个图形项上单击鼠标时,还显示图形项中的局部坐标
自定义图形视图组件
QGraphicsView
从QGraphicsView
继承定义一个类QWGraphicsView
,实现mouseMoveEvent()
事件和mousePressEvent()
事件,把鼠标事件转换为信号
自定义信号
类定义中,进行信号函数声明
触发信号处,采用emit
信号函数(实参列表); 来触发信号
对QMouseEvent
支持QPoint pos(),? button()
主窗口类定义与QGraphicsView组件升级
QMainWindow
类继承的类
resizeEvent()
事件
对QMainWindow
支持void resizeEvent(QResizeEvent*)
窗口初始化
对QGraphicsView
:
void setCursor(...)
void setMouseTracking(...)
void setDragMode(...)
// 依据视图坐标得到场景坐标
QPointF mapToScene(...)
int width()
int height()
QRectF sceneRect()
对QRectF支持:
int top()
int left()
int width()
int height()
对QString
支持QString asprintf(...)
对QGraphicsScene
支持QGraphicsItem* itemAt(QPointF, QTransform)
对QGraphicsItem
支持QPointF mapFromScene(...)
Graphics View系统初始化
对QRectF,QGraphicsScene
支持QGraphicsScene(QRectF),void addItem(...),void clearSelection()
对QGraphicsView
支持void setScene(QGraphicsScene*)
对QGraphicsRectItem/QGraphicsEllipseItem/QGraphicsEllipseItem
支持QGraphicsItem(QRectF),void setPos(...),void setFlags(...)
可视化设计窗体时,将QWGraphicsView
类对象名称命名为View
,且自动填充主窗口工作区
Graphics View绘图程序实例
实例功能
- 可创建矩形,椭圆,圆形,三角形,梯形,直线,文字等基本图形项
- 每个图形项都可被选择和拖动
- 图形项或整个视图可缩放和旋转
- 图形项重叠时,可调整前置或后置
- 多个图形项可组合,可解除组合
- 可删除选择的图形项
- 鼠标在视图上移动时,
会在状态栏显示视图坐标和场景坐标
- 鼠标单击某个图形项时,会显示图形项的局部坐标,会显示图形项的文字描述和编号
- 双击某个图形项时,会根据图形项的类型调用颜色对话框或字体对话框,
设置图形项的填充颜色,线条颜色,或文字的字体
- 选中某个图形项时,可进行按键操作,
Delete
键删除图形项,
PgUp
放大,
PgDn
缩小
空格键旋转90
度
上下左右光标键移动图形项
自定义图形视图类QWGraphicsView
事件处理--发自定义信号---设计槽函数处理
对QMouseEvent
支持QPoint pos(),? button()
主窗口设计
主窗口是一个从QMainWindow
继承的窗口类MainWindow
采用可视化设计
利用Action
创建两个工具栏
一个用于图形项的创建
一个用于图形项的各种操作
ItemId
和ItemDesciption
用于定义图形项的自定义数据的键
seqNum
用于给每个图形项编号,
frontZ
用于设置图形项的叠放顺序,数值越大,越在前面显示
backZ
用于设置图形项的叠放顺序,数值越小,越在后面显示
对QGraphicsScene
支持new QGraphicsScene(...)// 场景坐标系
对QGraphicsView
:
void setScene(...)// 视图与场景关联
void setCursor(...)//
void setMouseTracking(...)
void setDragMode(...)
对QWidget
支持void setCentralWidget(...),qsrand(...)// 随机数初始化
图形项的创建
主窗口左侧工具栏上的按钮用于创建各种标准的图形项
创建矩形使用QGraphicsRectItem
创建椭圆和圆使用QGraphicsEllipseItem
创建三角形和梯形使用QGraphicsPolygonItem
创建直线使用QGraphicsLineItem
创建文字使用QGraphicsTextItem
还有一些其他的标准图形项类
对QGraphicsEllipseItem
支持:
new QGraphicsEllipseItem(...)// 建立图形项坐标系
void setFlags(...)
void setBrush(...)
void setZValue(...)
void setPos(...)// 图形项中心在场景坐标系的位置
void setData(...)// 键值对
void setSelected(...)
对QGraphicsScene
:
void addItem(...) // 将QGraphicsItem与QGraphicsScene绑定
void clearSelection()
多个图形项叠加在一起时,ZValue
最大的显示在最前面
图形项操作
主窗口的另一个工具栏上的按钮实现图形项的缩放,旋转,组合等
- 缩放
对QGraphicsScene
支持? selectedItems()
对QGraphicsItem
支持void setScale(...)
对QGraphicsView
支持void scale(...)
- 旋转
对QGraphicsItem
支持void setRotation(...),int rotation()
对QGraphicsView
支持void rotate(...) // 正值表示顺时针旋转
- 恢复坐标变换
对QGraphicsItem
支持void resetTransform()
对QGraphicsView
支持void resetTransform()
- 叠放顺序
QGraphicsItem
的zValue()
表示图形项在Z轴的值
若有多个图形项叠加在一起
zValue()
值最大的显示在最前面
zValue()
值最小的显示在最后面
用setZValue()
可设置这个属性值
对QGraphicsItem
支持int zValue(),void setZValue(...)
- 图形项的组合
可将多个图形项组合为一个图形项
当做一个整体进行操作
使用QGraphicsItemGroup
类实现多个图形项的组合
QGraphicsItemGroup
是QGraphicsItem
的子类
对QGraphicsScene
支持void addItem(...),void clearSelection()
对QGraphicsItem
支持void setSelected(...),void clearFocus()
对QGraphicsItemGroup
支持void addToGroup(...),void setFlags(...),void setZValue(...),void setSelected(...)
一个组合对象也可被打散
使用QGraphicsScene
的destroyItemGroup()
可打散一个组合对象
这个函数打散组合,删除组合对象
但不删除原来组合里的图形项
对QGraphicsScene
支持void destroyItemGroup(...)
- 图形项的删除
使用QGraphicsScene
的removeItem()
函数删除某个图形项
对QGraphicsScene
支持void removeItem(....),? selectedItems()
鼠标与键盘操作
- 鼠标移动
鼠标在绘图视图上移动时,在状态栏显示光标处的视图坐标和场景坐标
时间参数为视图坐标
对QGraphicsView
支持QPointF mapToScene(...)// 视图坐标映射到场景坐标
- 鼠标单击
显示图形项局部坐标
提取其自定义信息进行显示
对QGraphicsScene
支持QGraphicsItem* itemAt(...)// 依据场景坐标在场景中进行命中测试
对QGraphicsItem
:
QPointF mapFromScene(...)// 由场景坐标得到图形项局部坐标
QVariant data(...)// 依据键,获取对应的值
- 鼠标双击
对QGraphicsView
支持QPointF mapToScene(...) // 将视图坐标映射到场景坐标
对QGraphicsScene
支持QGraphicsItem* itemAt(...)// 依据场景坐标,视图变换进行命中测试
对QGraphicsItem
支持int type(),qgraphicsitem_cast<X*>(xx)// QGraphicsItem基类到派生类的显示指针类型转换
对QGraphicsLineItem
支持QPen pen(),void setPen(...)
对QPen
支持QColor color(),void setColor(...)
对QColorDialog
支持QColor getColor(...)
对QGraphicsTextItem
支持QFont font(),void setFont(...)
对QFontDialog
支持QFont getFont(...)
自定义一个图形项时,需定义枚举常量Type
和函数type
枚举常量Type
的值必须大于UserType
模板函数
template<class T>
void setBrushColor(T* item)
{
QColor color = item->brush().color();
color = QColorDialog::getColor(color, NULL, "选择填充颜色");
if(color.isValid())
item->setBrush(QBrush(color));
}
- 按键操作
对QGraphicsScene
支持void removeItem(...)
对QGraphicsItem
:
void setRotation(...)
int rotation()
void setScale(...)
int scale()
void setX(...)
int x()
void setY(...)
int y()