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