欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > 《突破控件限制:用Qt绘图API解锁高级界面定制能力》

《突破控件限制:用Qt绘图API解锁高级界面定制能力》

2025/5/16 21:00:04 来源:https://blog.csdn.net/island1314/article/details/147272642  浏览:    关键词:《突破控件限制:用Qt绘图API解锁高级界面定制能力》

一、基本概念

虽然 Qt 已经内置了很多的控件,但是不能保证现有控件就可以应对所有场景。很多时候我们需要更强的 “自定制” 能力。

Qt 提供了画图相关的 API,允许我们在窗口上绘制任意的图形形状来完成更复杂的界面设计

  • 所谓的 “控件” 本质上也是通过画图的方式画上去的。

  • 画图 API 和控件之间的关系,可以类比成机器指令和高级语言之间的关系。

  • 控件是对画图 API 的进一步封装,画图 API 是控件的底层实现。

【绘图 API 核心类】

说明
QPainter“绘画者” 或者 “画家” ==> 用来绘图的对象,提供了一系列 drawXXX 方法,可以允许我们绘制各种图形.
QPaintDevice“画板” ==> 描述了 QPainter 把图形画到哪个对象上. 像咱们之前用过的 QWidget 也是一种 QPaintDevice (QWidget 是 QPaintDevice 的子类).
QPen“画笔” ==> 描述了 QPainter 画出来的线是什么样的.
QBrush“画刷” ==> 描述了 QPainter 填充一个区域是什么样的.

绘图 API 的使用一般不会在 QWidget 的构造函数中使用,而是要放到 paintEvent 事件中,在这里进行调用

paintEvent 会在以下情况下被触发:

  • 控件首次创建。

  • 控件被遮挡,再解除遮挡。

  • 窗口最小化,再恢复。

  • 控件大小发生变化时。

  • 主动调用 repaint() 或者 update() 方法(这两个方法都是 QWidget 的方法)。

二、绘制各种形状

1. 绘制线段

void drawLine(const QPoint &p1, const QPoint &p2); 
参数:p1:绘制起点坐标p2:绘制终点坐标void drawLine ( int x1, int y1, int x2, int y2 ); 
参数:x1,y1:绘制起点坐标x2,y2:绘制终点坐标    

【案例】

在 “widget.h” 头文件中声明绘图事件,然后在 “widget.cpp” 文件中重写 paintEvent() 方法,代码如下:

void Widget::paintEvent(QPaintEvent *event)
{(void) event;// 绘图工作就会放到这里来执行.QPainter painter(this);// 画一个线段.painter.drawLine(20, 20, 200, 20);painter.drawLine(QPoint(20, 100), QPoint(200, 100));painter.drawLine(20, 20, 100, 300);
}

实现效果如下:

image-20250203151128560

2. 绘制矩形

void QPainter::drawRect(int x, int y, int width, int height);    
参数:x:窗口横坐标;y:窗口纵坐标;width:所绘制矩形的宽度;height:所绘制矩形的⾼度;

【案例】:和绘制线段操作类似,代码如下:

void Widget::paintEvent(QPaintEvent *event)
{(void) event;QPainter painter(this);// 画一个矩形.painter.drawRect(100, 100, 300, 200);
}

运行程序,如下:

image-20250203151352877

3. 绘制圆形

void QPainter::drawEllipse(const QPoint &center, int rx, int ry) 
参数:center:中⼼点坐标rx:横坐标ry:纵坐标

【案例】:和上面类似,如下:

// 画圆形.
painter.drawEllipse(200, 200, 400, 100);

运行程序,如下:

image-20250203151454098

4. 绘制文本

🔥 QPainter 类中不仅提供了绘制图形的功能,还可以使用 QPainter::drawText() 函数来绘制文字,也可以使用 QPainter::setFont() 设置字体等信息。

【案例】:基于上面类似操作

QFont font("微软雅黑", 24);
painter.setFont(font);
// 绘制文本.
painter.drawText(0, 100, "hello");
  • 注意理解 drawText 中的坐标位置
  • 此处的 0 横坐标:表示 文字 最左侧位置
  • 此处 100 纵坐标:表示 文字 基线位置(英语单词本上四线格从上往下的第三根线)

运行程序,如下:

image-20250203151851081

  • 但是看到这,绘制的形状外貌信息还是太过单调,因此就需要用 画笔 调节

5. 设置画笔

💢 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)

画笔的风格有:
img

【案例】:基于之前操作

QPen pen;
// 设置成红色的线条
pen.setColor(QColor(255, 0, 0));
// 设置线条的粗细.
pen.setWidth(5);
// 设置线条的风格
pen.setStyle(Qt::DashLine);// 让 painter 对象应用 pen 对象
painter.setPen(pen);
// 画圆形.
painter.drawEllipse(200, 200, 400, 100);

运行程序,如下:

image-20250203152720652

6. 绘制画刷

在 Qt 中,画刷是使用 QBrush 类来描述,画刷大多用于填充。

  • QBrush 定义了 QPainter 的填充模式,具有样式、颜色、渐变以及纹理等属性。

  • 画刷的格式中定义了 填充 的样式

使用 Qt::BrushStyle 枚举,默认值是 Qt::NoBrush,也就是不进行任何填充

可以通过 Qt 助手查找画刷的格式。如下图示:
img

设置画刷主要通过 void QPen::setBrush(const QBrush &brush) 方法,其参数为画刷的格式。

【案例】:基于之前操作

QBrush brush;
brush.setColor(QColor(0, 255, 0));
brush.setStyle(Qt::SolidPattern);
brush.setStyle(Qt::CrossPattern);
painter.setBrush(brush);// 画圆形.
painter.drawEllipse(200, 200, 400, 100);

运行程序,如下:

image-20250203153024386

三、绘制图片

Qt 提供了四个类来处理图像数据:QImage、QPixmap、QBitmap 和 QPicture

  • 其中QImage主要用来进行 I/O 处理,它对 I/O 处理操作进行了优化,而且可以用来直接访问和操作像素

  • QPixmap 主要用来在屏幕上显示图像,它对屏幕上的显示图像进行优化;

  • QBitmap 是 QPixmap 的子类,用来 处理颜色深度为 1 的图像,即只能显示黑白两种颜色

  • QPicture 用来记录并重演 QPainter 命令。

1. 绘制简单图片

新建项目,并且创建 qrc 文件,引入图片,如下:

image-20250203155201045

在 “widget.h” 头文件中声明绘图事件,然后在 “widget.cpp” 文件中重写 paintEvent() 方法,代码如下:

void Widget::paintEvent(QPaintEvent *event)
{(void) event;QPainter painter(this);//画图片QPixmap pixmap(":/tree.jpg");painter.drawPixmap(100, 100, pixmap); // 位置是相对于左上角
}

运行程序,结果如下:

image-20250203155808583

2. 平移图片

平移图片实际是通过改变坐标来实现。QPainter 类中提供了 *translate()* 函数来实现坐标原点的改变。

painter.translate(100,100);

3. 缩放图片

painter.drawPixmap(0, 0, 400, 300, pixmap);

运行程序,结果如下:

image-20250203155959659

4. 旋转图片

图片的旋转使用的是 QPainter 类中的 rotate() 函数,它默认是 以原点为中心 进行旋转的。如果要改变旋转的中心,可以使用 translate() 函数完成。

img

// 图片旋转:本质是把 QPainer 对象进行旋转,这样绘制内容也发生旋转
painter.rotate(180);
painter.translate(-800, -600);
painter.drawPixmap(100, 100, 400, 300,pixmap);

四、其他设置

1. 移动画家位置

有时候在绘制多个图形时,想使用同一坐标位置,那么绘制出来的图形肯定会重合,此时,可以通过移动画家的位置来使图形不发生重合。

【案例】:

代码如下:

void Widget::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.drawEllipse(QPoint(100, 200), 50, 50);painter.translate(100, 100); // 让画家移动painter.drawEllipse(QPoint(100, 200), 50, 50);
}

image-20250203161848456

2. 保存 / 加载画家的状态

在绘制图形的过程中,可以通过 save() 函数来保存画家的状态,使用 restore() 函数还原画家状态。

save() 函数原型如下:

img

restore() 函数原型如下:

img

【案例】如下:

image-20250203162617317

💡说明:

在画第三个圆之前,由于还原了画家的状态,所以此时画家的位置坐标会移动到画家状态保存的地方,所以在绘制第三个圆的位置时实际是和第二个圆发生了 重叠

五、特殊的绘图设备

前面的代码中我们是使用 QWidget 作为绘图设备,在 Qt 中还存在下列三个比较特殊的绘图设备。

  • QPixmap 用于在显示器上显示图片
  • QImage 用于对图片进行像素级修改
  • QPicture 用于对 QPainter 的一系列操作进行存档

1. QPixmap

QPixmap 核心特性:

  • 使用 QPainter 直接在上面进行绘制图形。

  • 通过文件路径加载并显示图片。

  • 搭配 QPainter 的 drawPixmap() 函数,可以把这个图片绘制到⼀个 QLabel、QPushButton 等控件上。

  • 和系统 / 显示设备强相关,不同系统 / 显示设备下,QPixmap 的显示可能 会有所差别

代码如下:

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPixmap pix(500, 500);QPainter painter(&pix);painter.setPen(Qt::red); // 设置画笔颜色painter.drawEllipse(QPoint(100, 100),100, 100); // 画圆pix.save("D:/C++/qt-learning/Scode/learn9-Painter-tools/pix.png");
}

实现效果:

image-20250203163129239

2. QImage

QImage 的核心特性:

  • 使用 QPainter 直接在上面进行绘制图形。
  • 通过文件路径加载并显示图片。
  • 能够针对图片进行像素级别的操作(操作某个指定的像素)。
  • 独立于硬件的绘制系统,能够在不同系统之上提供一致的显示。

【QImage 作为绘图设备的使用】

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QImage img(500, 500, QImage::Format_RGB32);img.fill(Qt::white); // 填充色:白色,默认为黑色QPainter painter(&img);painter.drawEllipse(QPoint(100, 100),100, 100); // 画圆img.save("D:/C++/qt-learning/Scode/learn9-Painter-tools/img.jpg");
}

实现效果:

image-20250203163857305

【QImage 绘图时对像素的修改】

#include "widget.h"
#include <QPainter>Widget::Widget(QWidget *parent): QWidget(parent)
{
}void Widget::paintEvent(QPaintEvent *)
{QPainter painter(this); // 实例化画家对象QImage img;img.load(":/pic.jpg"); // 加载图片// 修改像素点for(int i = 100; i < 200; i++){for(int j = 100; j < 200; j++){QRgb rgb = qRgb(0, 0, 255);img.setPixel(i, j, rgb);}}painter.drawImage(0, 0, img);
}
  • 通过 setPixel 设置某个像素的颜色值
  • 使用 qRgb 表示一个具体的颜色

3. QPicture

QPicture 核心特性:

  1. 使用 QPainter 直接在上面进行绘制图形。
  2. 通过文件路径加载并显示图片。
  3. 能够记录 QPainter 的操作步骤。
  4. 独立于硬件的绘制系统,能够在不同系统之上提供⼀致的显示。

注意 :QPicture 加载的必须是自身的存档文件,而不能是任意的 png, jpg 等图片文件

如果要记录下 QPainter 的命令

  • 首先要使用 QPainter::begin() 函数,将 QPicture 实例作为参数传递进去,以便告诉系统开始记录
  • 记录完毕后使用 QPainter::end() 命令终止。

img

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词