目录
[2.1 绘制线段](#2.1 绘制线段)
[2.2 绘制矩形](#2.2 绘制矩形)
[2.3 绘制圆形](#2.3 绘制圆形)
[2.4 绘制文本](#2.4 绘制文本)
[2.5 设置画笔](#2.5 设置画笔)
[2.6 设置画刷](#2.6 设置画刷)
[3.1 绘制简单图片](#3.1 绘制简单图片)
[3.2 平移图片](#3.2 平移图片)
[3.3 缩放图片](#3.3 缩放图片)
[3.4 旋转图片](#3.4 旋转图片)
[4.1 移动画家位置](#4.1 移动画家位置)
[4.2 保存/加载画家的状态](#4.2 保存/加载画家的状态)
[5.1 QPixmap](#5.1 QPixmap)
[5.2 QImage](#5.2 QImage)
[5.3 QPicture](#5.3 QPicture)
(一)基本概念
虽然Qt已经内置了很多的控件,但是不能保证现有控件就可以应对所有场景.
很多时候我们需要更强的"自定制"能力.
Qt 提供了画图相关的API,可以允许我们在窗口上绘制任意的图形形状,来完成更复杂的界面设计.
- 所谓的"控件",本质上也是通过画图的方式画上去的.
- 画图API和控件之间的关系,可以类比成机器指令和高级语言之间的关系.
- 控件是对画图API的进⼀步封装;画图API是控件的底层实现.
绘图API核心类
绘图API的使用,⼀般不会在QWidget的构造函数中使用,而是要放到paintEvent 事件中.
关于 paintEvent
paintEvent 会在以下情况下被触发:
- 控件首次创建.
- 控件被遮挡,再解除遮挡.
- 窗口最小化,再恢复.
- 控件⼤小发生变化时.
- 主动调用 repaint() 或者 ...... update() 方法.(这两个方法都是 QWidget 的方法).
- 因此,如果把绘图api放到构造函数中调用,那么⼀旦出现上述的情况,界面的绘制效果就⽆法确保符合预期了.
(二)绘制各种形状
2.1 绘制线段
示例1:
bash
void drawLine(const QPoint &p1, const QPoint &p2);
参数:
p1:绘制起点坐标
p2:绘制终点坐标
void drawLine {int x1, int y1, int x2, int y2};
参数:
x1,y1:绘制起点坐标
x2,y2:绘制终点坐标
1、在"widget.h"头文件中声明绘图事件;
2、在"widget.cpp"文件中重写paintEvent()方法;
实现效果如下:
2.2 绘制矩形
bash
void QPainter::drawRect(int x, int y, int width, int height);
参数:
x:窗⼝横坐标;
y:窗⼝纵坐标;
width:所绘制矩形的宽度;
height:所绘制矩形的⾼度;
示例如下:
2.3 绘制圆形
bash
void QPainter::drawEllipse(constQPoint ¢er, int rx, int ry);
参数:
center:中⼼点坐标
rx:横坐标
ry:纵坐标
示例如下:
2.4 绘制文本
QPainter类中不仅提供了绘制图形的功能,还可以使用QPainter::drawText()函数来绘制文字,也可以使用QPainter::setFont() 设置字体等信息。
示例如下:
实现效果如下:
2.5 设置画笔
QPainter 在绘制时,是有⼀个默认的画笔的。在使用时也可以自定义画笔。在Qt中,QPen类中定义了QPainter应该如何绘制形状、线条和轮廓。同时通过QPen类可以设置画笔的线宽、颜色、样式、 画刷等。
画笔的颜⾊可以在实例化画笔对象时进行设置,画笔的宽度是通过setWidth()⽅法进行设置,画笔的风格是通过setStyle()⽅法进行设置,设置画刷主要是通过setBrush()⽅法。
- 设置画笔颜色:QPen::QPen(constQColor&color) 画笔的颜色主要是通过QColor类设置;
- 设置画笔宽度:voidQPen::setWidth(intwidth)
- 设置画笔风格:voidQPen::setStyle(Qt::PenStylestyle)
画笔的风格有:
示例:画笔的使用
实现效果如下:
2.6 设置画刷
在Qt中,画刷是使用QBrush类来描述,画刷大多用于填充。QBrush定义了QPainter的填充模式, 具有样式、颜色、渐变以及纹理等属性。
画刷的格式中定义了填充的样式,使用Qt::BrushStyle枚举,默认值是Qt::NoBrush,也就是不进行任何填充。可以通过Qt助⼿查找画刷的格式。如下图示:
- 设置画刷主要通过**void QPen::setBrush(const QBrush& brush)**方法,其参数为画刷的格式。
示例如下:
实现效果:
(三)绘制图片
Qt 提供了四个类来处理图像数据:QImage、QPixmap、QBitmap和QPicture,它们都是常用的绘图设备。其中QImage主要用来进行I/O处理,它对I/O处理操作进行了优化,而且可以用来直接访问和操作像素;QPixmap主要用来在屏幕上显示图像,它对在屏幕上显示图像进行了优化;QBitmap 是QPixmap的⼦类,用来处理颜色深度为1的图像,即只能显示黑白两种颜色;QPicture用来记录并 重演QPainter命令。本期只讲解QPixmap。
3.1 绘制简单图片
1. 新建Qt项目,基类选择QWidget,项目名称为QPainter。在"widget.h"头文件中声明绘画事 件;如下图示:
2. 添加资源文件。( ⾸先准备⼀些图⽚资源文件,并将这些图⽚资源文放在同⼀个文件夹中,将该文件夹复制到本项目中**)**
3. 选中项目文件,鼠标右键------->addnew... ,点击"addnew..."之后选择"Choose...",给资源文件命名,在点击"下⼀步",最后点击"完成"
4. 给资源文件添加前缀,并将资源文件添加至项目中。将所有的资源文件添加到项目中,方便后续使用。最后点击"构建并运行"按钮,将资源文件添加到项目中
5. 在"widget.cpp"文件中实现画图片功能;
实现效果如下:
3.2 平移图片
平移图片实际是通过改变坐标来实现。QPainter类中提供了translate()函数来实现坐标原点的改变。
3.3 缩放图片
在Qt中,图片的放大和缩小可以使用QPainter类中的drawPixmap()函数来实现。
示例如下:
实现效果如下:
3.4 旋转图片
图⽚的旋转使用的是QPainter类中的rotate()函数,它默认是以原点为中心进行旋转的。如果要改变旋转的中心,可以使用 translate()函数完成。
示例如下:
实现效果如下:
(四)其他设置
4.1 移动画家位置
有时候在绘制多个图形时,想使用同⼀坐标位置,那么绘制出来的图形肯定会重合,此时,可以通过移动画家的位置来使图形不发生重合。
示例1:未移动画家位置
实现效果如下:
示例2:移动画家位置
- 使用 translate 移动画家所在位置.
实现效果如下:
4.2 保存/加载画家的状态
在绘制图形的过程中,可以通过save()函数来保存画家的状态,使⽤restore()函数还原画家状态。
save() 函数原型如下:
示例如下:
实现效果如下:
说明:
- 上述示例中,在画第三个圆之前,由于还原了画家的状态,所以此时画家的位置坐标会移动到画家状态保存的地方,所以在绘制第三个圆的位置时实际是和第⼆个圆发生了重叠。
(五)特殊的绘图设备
前面的代码中我们是使用QWidget作为绘图设备.在Qt中还存在下列三个比较特殊的绘图设备.此处简要介绍.
- QPixmap用于在显示器上显示图片.
- QImage用于对图片进行像素级修改.
- QPicture 用于对QPainter的⼀系列操作进行存档.
5.1 QPixmap
QPixmap核心特性:
- 使用QPainter直接在上⾯进行绘制图形.
- 通过文件路径加载并显示图⽚.
- 搭配QPainter的drawPixmap()函数,可以把这个图⽚绘制到⼀个QLabel、QPushButton等控件上.
- 和系统/显示设备强相关,不同系统/显示设备下,QPixmap的显示可能会有所差别.
示例如下:
实现效果:
5.2 QImage
QImage的核心特性:
- 使用QPainter直接在上⾯进行绘制图形.
- 通过文件路径加载并显示图⽚.
- 能够针对图片进行像素级别的操作(操作某个指定的像素).
- 独立于硬件的绘制系统,能够在不同系统之上提供⼀致的显示.
代码示例:QImage作为绘图设备的使用
5.3 QPicture
QPicture 核心特性:
- 使用QPainter直接在上面进行绘制图形.
- 通过文件路径加载并显示图片.
- 能够记录QPainter的操作步骤.
- 独力于硬件的绘制系统,能够在不同系统之上提供⼀致的显示
注意: QPicture 加载的必须是自身的存档⽂件,而不能是任意的png,jpg等图片文件.
QPicture类似于很多游戏的Replay功能.
例如像war3这样的经典游戏,即使是⼀场60分钟的膀胱局,生成的replay文件,也不过几百个KB.
此处的Replay功能并非是把整个游戏画面都录制保存下来,而是记录了地图中发生的所有事 件(地图元素,玩家单位操作,中立生物行为等...).
当回放Replay的时候其实就是把上述记录的事件再⼀条⼀条的执行⼀遍即可还原之前的游戏 场景了.
如果要记录下QPainter的命令,⾸先要使⽤QPainter::begin()函数,将QPicture实例作为参数传递 进去,以便告诉系统开始记录,记录完毕后使用QPainter::end()命令终⽌。如下示例:
实现效果:
通过QPicture重现绘图指令后,实现的效果如下: