前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >《突破控件限制:用Qt绘图API解锁高级界面定制能力》

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

作者头像
IsLand1314
发布于 2025-04-17 05:04:02
发布于 2025-04-17 05:04:02
21410
代码可运行
举报
文章被收录于专栏:学习之路学习之路
运行总次数:0
代码可运行

一、基本概念

虽然 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. 绘制线段
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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() 方法,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
image-20250203151128560
2. 绘制矩形
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void QPainter::drawRect(int x, int y, int width, int height);    
参数:
    x:窗口横坐标;
    y:窗口纵坐标;
    width:所绘制矩形的宽度;
    height:所绘制矩形的⾼度;

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void Widget::paintEvent(QPaintEvent *event)
{
    (void) event;
    QPainter painter(this);
    // 画一个矩形.
    painter.drawRect(100, 100, 300, 200);
}

运行程序,如下:

image-20250203151352877
image-20250203151352877
3. 绘制圆形
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void QPainter::drawEllipse(const QPoint &center, int rx, int ry) 
参数:
    center:中⼼点坐标
    rx:横坐标
    ry:纵坐标

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 画圆形.
painter.drawEllipse(200, 200, 400, 100);

运行程序,如下:

image-20250203151454098
image-20250203151454098
4. 绘制文本

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

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

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

运行程序,如下:

image-20250203151851081
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
img

【案例】:基于之前操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
image-20250203152720652
6. 绘制画刷

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

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

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

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

img
img

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

【案例】:基于之前操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
image-20250203153024386

三、绘制图片

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

  • 其中QImage主要用来进行 I/O 处理,它对 I/O 处理操作进行了优化,而且可以用来直接访问和操作像素
  • QPixmap 主要用来在屏幕上显示图像,它对屏幕上的显示图像进行优化;
  • QBitmap 是 QPixmap 的子类,用来 处理颜色深度为 1 的图像,即只能显示黑白两种颜色
  • QPicture 用来记录并重演 QPainter 命令。
1. 绘制简单图片

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

image-20250203155201045
image-20250203155201045

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void Widget::paintEvent(QPaintEvent *event)
{
    (void) event;
    QPainter painter(this);
    //画图片
    QPixmap pixmap(":/tree.jpg");
    painter.drawPixmap(100, 100, pixmap); // 位置是相对于左上角
}

运行程序,结果如下:

image-20250203155808583
image-20250203155808583
2. 平移图片

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
painter.translate(100,100);
3. 缩放图片
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
painter.drawPixmap(0, 0, 400, 300, pixmap);

运行程序,结果如下:

image-20250203155959659
image-20250203155959659
4. 旋转图片

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

img
img
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 图片旋转:本质是把 QPainer 对象进行旋转,这样绘制内容也发生旋转
painter.rotate(180);
painter.translate(-800, -600);
painter.drawPixmap(100, 100, 400, 300,pixmap);

四、其他设置

1. 移动画家位置

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

【案例】:

代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
image-20250203161848456
2. 保存 / 加载画家的状态

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

save() 函数原型如下:

img
img

restore() 函数原型如下:

img
img

【案例】如下:

image-20250203162617317
image-20250203162617317

💡说明:

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

五、特殊的绘图设备

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

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

QPixmap 核心特性:

  • 使用 QPainter 直接在上面进行绘制图形。
  • 通过文件路径加载并显示图片。
  • 搭配 QPainter 的 drawPixmap() 函数,可以把这个图片绘制到⼀个 QLabel、QPushButton 等控件上。
  • 和系统 / 显示设备强相关,不同系统 / 显示设备下,QPixmap 的显示可能 会有所差别

代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
image-20250203163129239
2. QImage

QImage 的核心特性:

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
image-20250203163857305

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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
img
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
您好,您参加的【玩转Cloud Studio】第二季获奖名单出来啦:https://cloud.tencent.com/developer/article/2269353,文末可查看名单~恭喜您获奖哦,请您联系腾讯云开发者社区助理(微信号:yun_assistant)填写收货信息,完成兑奖。
您好,您参加的【玩转Cloud Studio】第二季获奖名单出来啦:https://cloud.tencent.com/developer/article/2269353,文末可查看名单~恭喜您获奖哦,请您联系腾讯云开发者社区助理(微信号:yun_assistant)填写收货信息,完成兑奖。
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
【QT】绘图
绘图可以帮助我们实现应对多种场景的功能,因为虽然Qt内部内置了很多控件,但是它们不能满足所有要求,我们就可以通过绘图来实现自定义图形
s-little-monster
2024/11/20
1120
【QT】绘图
QT学习笔记15绘图和绘图设备
Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。
全栈程序员站长
2022/08/02
1.7K0
QT学习笔记15绘图和绘图设备
QT入门学习——从鼠标事件,定时器事件到绘图学习,绘图设备
Arya
2024/11/06
2860
QT入门学习——从鼠标事件,定时器事件到绘图学习,绘图设备
Qt入门系列(三)
选装父文件—>添加文件-->Qt--->设计师界面->命名smallWidget(简称sw)
用户9831583
2022/06/16
1.2K0
Qt入门系列(三)
Qt5实战第五篇:图形与绘图
Qt5 提供了强大的二维图形绘制功能,通过 QPainter 类,开发者可以在窗口部件或其他绘制设备上进行绘图。此外,Qt 还支持矢量图形、图像处理、动画以及高级绘图功能,使得开发图形界面应用程序变得简单而高效。
china马斯克
2024/12/28
3750
Qt 之图形(QPainter 的基本绘图)「建议收藏」
Qt 中提供了强大的 2D 绘图系统,可以使用相同的 API 在屏幕和绘图设备上进行绘制,它主要基于QPainter、QPaintDevice 和 QPaintEngine 这三个类。
全栈程序员站长
2022/11/18
6.2K0
Qt 之图形(QPainter 的基本绘图)「建议收藏」
Qt中基本的绘图方法
Qt中实现绘图功能和其他的库差不多,主要靠Painter,Pen,Brush之类的东西进行描绘。这里主要牵涉到QPainter,QPen,QBrush三个类,用法也很简单。下面主要是实现一个全面显示各种图形的程序,定义了两个类,一个负责绘图区,一个负责用户交互,这里先介绍绘图区的类。
mythsman
2022/11/14
7940
Qt的双缓冲技术(double buffering)
Qt的双缓冲技术(double buffering)是Qt绘画机制的一部分,是一种在Qt4中被全面采用的技术。其核心是:把一个窗口部件渲染到一个脱屏pixmap(off- screen pixmap)中,然后再把这个pixmap复制到显示屏幕上。这样做的目的是用于消除屏幕的闪烁并且因而界面会显得更漂亮。Qt4中,Qt会自动处理这些情况,所以在普通的绘画中,我们不必要关注这些内容。
全栈程序员站长
2022/09/03
2.3K0
Python Qt GUI设计:QPainter、QPen、QBrush和QPixmap窗口绘图类(基础篇—17)
本篇博文主要介绍如何实现在窗口中绘图,在 PyQt5中,一般可以通过QPainter、QPen、QBrush和QPixmap这四个类来实现绘图功能。其中,QPixmap的作用是加载并呈现本地图像,而图像的呈现本质上也是通过绘图方式实现的。
不脱发的程序猿
2021/10/26
2.6K0
28.QT-QPainter介绍
介绍 可以在QPaintDevice类上绘制各种图形 QPaintDevice类表示QPainter的绘图设备(画布) QpaintDevice子类有QImage、QOpenGLPaintDevice、QWidget 等 所以, QPainter可以在QImage、QOpenGLPaintDevice、QWidget上进行绘制图形 QPainter只能在类对象的paintEvent()函数中绘制图形 QPainter类的成员角色有: QPen         : 用于绘制几何图形的边缘,由颜色,宽度,线风格
诺谦
2018/06/21
1.9K0
【QT】QT基本图形绘制
**注意:**QPainter画弧度所使用的角度值,是以1/16°为单位的,在画弧度的时候1°用16表示。
半生瓜的blog
2023/05/13
1.1K0
【QT】QT基本图形绘制
Qt中国象棋一—— Qt 2D 绘图入门
最近想用Qt写一个中国象棋的项目,在网上找了几个例子后,发现关于绘图部分基础为0 ,于是根据项目需要学习一下。查了一些网上的资料,在此总结一下;我比较喜欢的方式是用到什么学什么,或者自己想做一个东西,这样学习起来目的性比较强,可以快速进入。
用户5908113
2019/10/29
1.9K0
PyQt5 基本窗口控件(绘图类 / 拖拽 / 剪贴板 / 日历时间 / 菜单、工具、状态栏 / 打印)
learn from 《PyQt5 快速开发与实战》 https://doc.qt.io/qtforpython/index.html https://www.riverbankcomputing.com/static/Docs/PyQt5
Michael阿明
2022/05/10
2K0
PyQt5 基本窗口控件(绘图类 / 拖拽 / 剪贴板 / 日历时间 / 菜单、工具、状态栏 / 打印)
Qt自绘系列-一堆甜甜圈
❝使用QPainter画甜甜圈。❞ 1. 实现 将甜甜圈绘制在QPixmap中,最后再绘制在窗口中。 甜甜圈使用QLinearGradient实现渐变效果。 设置画笔的宽度实现甜甜圈的宽度。 最后使用drawEllipse方法画圆。 2. 核心代码 绘制单个甜甜圈代码。 QPixmap Donut::createOneDount(int radius, int width, const QColor &color) { QPixmap pixmap = QPixmap(radius, radiu
Qt君
2023/03/17
3200
Qt自绘系列-一堆甜甜圈
Qt自绘系列-透明时钟
❝使用QPainter画透明时钟,还可拖动。❞ 一、演示 二、实现 画背景图,一个白色圆环,60个圆点和12个数字组成。 QPixmap pixmap = QPixmap(width, height); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHints(QPainter::Smooth
Qt君
2023/03/17
7630
Qt自绘系列-透明时钟
Qt编写自定义控件9-导航按钮控件
导航按钮控件,主要用于各种漂亮精美的导航条,我们经常在web中看到导航条都非常精美,都是html+css+js实现的,还自带动画过度效果,Qt提供的qss其实也是无敌的,支持基本上所有的CSS2属性,配合QPainter这个无敌大法工具,没有什么不能绘制的。这个控件总结了大部分的导航条样式,比如左侧+右侧+顶部+底部,线条指示器,倒三角指示器等。还可以在导航条前面加上图标等,就显得更加有特色。有了此控件,再也不用担心没有精美的导航了。
feiyangqingyun
2019/08/23
2.7K0
Qt编写自定义控件9-导航按钮控件
Qt编写自定义控件62-探探雷达
随着移动互联网的盛行,现在手机APP大行其道,每个人的手机没有十几个APP都不好意思说自己是现代人,各种聊天、购物、直播、小视频等APP,有个陌生人社交的APP叫探探,本人用过几次,当然不是去为了找对象,而是纯粹为了好玩研究下他的U设计和软件逻辑流程等,其中有个雷达控件,单击以后可以搜索附近的异性进行配对,这个雷达控件的效果蛮好的,于是手痒琢磨着用Qt来实现一个,毕竟自己写了150多个控件了,已经上瘾了,对各种效果都如鱼得水,看到各种效果都不自然的想到编码思路等。
feiyangqingyun
2019/10/16
8810
Qt编写自定义控件62-探探雷达
Qt自定义控件之仪表盘的完整实现
基于QT的仪表盘有很多种办法,比如使用QWT或Echart组件,或者基于QT的绘图功能绘制,或者基于美工提供的图片的基础上增加动态效果。然而搞明白QT自定义控件的绘图后,这种实现是最简单的。且定制度高,想要什么效果就可以自己绘制个。这里介绍下Qt自定义控件之仪表盘的完整实现。
杨永贞
2022/10/04
2.5K0
Qt自定义控件之仪表盘的完整实现
【QT】QT事件处理
QT中,事件作为一个对象,继承自QEvent类,常见的有键盘事件QKeyEvent、鼠标事件QMouseEvent和定时器事件QTimerEvent等。QT中,任何QObject子类示例都可以接收和处理事件。实际编程中通常实现部件的paintEvent()、mousePressEvent()等事件处理函数来处理特定部件的特定事件。
半生瓜的blog
2023/05/13
1.7K0
【QT】QT事件处理
小白白也能学会的 PyQt 教程 —— 图像类及图像相关基础类介绍
图,貌似是一个好看的 UI 中必不可少的东西,精美的 UI 中不可避免的会使用一些奇特的各种图像元素来提升用户体验。对于开发者而言,如何在应用程序中有效地显示和处理图像成为一个重要的课题。在Python中,PyQt库是一个强大而灵活的选择,它提供了丰富的图像处理类和功能。
繁依Fanyi
2023/05/20
3.2K0
推荐阅读
相关推荐
【QT】绘图
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档