尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
深入浅出 Qt 绘图机制:从 QPainter 到四大图像类解析
个人主页Cx330❄️个人专栏《C语言》《LeetCode刷题集》《数据结构-初阶》《C知识分享》《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔《Git深度解析》:版本管理实战全解 《Qt 极境架构》MySQL 核心技术与实战心向往之行必能Cx330的简介目录前言一、 Qt 绘图四大核心角色1.2 绘图的核心原则二. 基础绘图绘制形状与文本2.1 绘制基础形状2.1.1 绘制线段2.1.2 绘制矩形2.1.3 绘制圆形 / 椭圆2.1.3 绘制圆形 / 椭圆2.2 绘制文本2.3 自定义画笔与画刷2.3.1 自定义画笔2.3.2 自定义画刷三. 图片处理绘制、缩放与旋转3.1 绘制图片QPixmap3.2 图片平移与旋转前言在 Qt 开发中我们经常使用各种各样的控件如QPushButton、QLineEdit、QLabel等。但你是否思考过这些控件究竟是如何呈现到屏幕上的答案非常简单本质上它们都是“画”出来的。Qt 已经提前帮我们绘制好了各种通用控件拿来即用。但在实际项目中当预设控件无法满足特殊需求时我们就需要利用 Qt 提供的绘图 API 手动 DIY 自定义控件与视觉效果。本文将根据 Qt 绘图的核心知识体系由浅入深解析 Qt 的绘图机制、核心组件、绘制事件机制以及图像处理类。一、 Qt 绘图四大核心角色Qt 的绘图系统采用了一套现实生活中“画画”的拟人化设计概念类名比喻作用与功能描述QPainter绘图者画师提供具体的绘图方法画线、画矩形、画文字等负责执行绘画动作。QPaintDevice画板绘图设备绘图的目标载体。QWidget是QPaintDevice的子类因此所有窗口控件都可以作为画板。QPen画笔用于绘制图形的轮廓线控制线条的颜色、粗细、线型实线、虚线等。QBrush画刷用于填充封闭图形的内部区域控制填充的颜色、渐变色或纹理图案。1.2 绘图的核心原则绘图时机绘图操作必须在paintEvent事件中执行该事件会在控件创建、大小改变、被遮挡恢复等场景下自动触发也可通过repaint()或update()主动触发。设备无关性QPainter 可在任意 QPaintDevice 子类上绘图无论是窗口QWidget、图片QPixmap还是像素缓冲区QImage接口完全一致。状态管理QPainter 支持save()保存当前状态和restore()恢复之前状态方便复杂绘图中的状态切换。二. 基础绘图绘制形状与文本Qt 绘图 API 支持绘制线段、矩形、圆形、文本等基础元素掌握这些是实现复杂效果的前提。2.1 绘制基础形状2.1.1 绘制线段通过drawLine方法绘制线段支持两种参数形式QPoint坐标对或直接传入 x、y 坐标void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); // 以当前窗口为画板 // 方式1使用QPoint指定起点和终点 painter.drawLine(QPoint(20, 20), QPoint(200, 20)); // 方式2直接传入x1,y1,x2,y2 painter.drawLine(20, 100, 200, 100); }2.1.2 绘制矩形drawRect方法接收矩形左上角坐标和宽高void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); // 绘制左上角(20,20)、宽100、高50的矩形 painter.drawRect(20, 20, 100, 50); }2.1.3 绘制圆形 / 椭圆drawEllipse方法通过中心点坐标和 x、y 轴半径绘制当 x、y 半径相等时即为圆形void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); // 绘制中心点(100,100)、半径50的圆形 painter.drawEllipse(QPoint(100, 100), 50, 50); // 绘制椭圆x半径30y半径50 painter.drawEllipse(QPoint(250, 100), 30, 50); }2.1.3 绘制圆形 / 椭圆drawEllipse方法通过中心点坐标和 x、y 轴半径绘制当 x、y 半径相等时即为圆形void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); // 绘制中心点(100,100)、半径50的圆形 painter.drawEllipse(QPoint(100, 100), 50, 50); // 绘制椭圆x半径30y半径50 painter.drawEllipse(QPoint(250, 100), 30, 50); }2.2 绘制文本通过drawText绘制文本支持设置字体 、颜色等样式void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); // 设置字体华文行楷24号 QFont font(华文行楷, 24); painter.setFont(font); // 设置文本颜色为红色 painter.setPen(Qt::red); // 在矩形区域(100,200,600,150)内绘制文本自动换行 painter.drawText(QRect(100, 200, 600, 150), 天行健君子以自强不息); }2.3 自定义画笔与画刷默认的画笔和画刷样式单一通过 QPen 和 QBrush 可实现个性化效果。2.3.1 自定义画笔QPen支持设置颜色、宽度、线条样式void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); QPen pen(QColor(255, 0, 0)); // 红色画笔 pen.setWidth(3); // 线宽3像素 pen.setStyle(Qt::DashLine); // 虚线样式可选SolidLine、DotLine等 painter.setPen(pen); // 画家使用该画笔 painter.drawEllipse(QPoint(100, 100), 50, 50); }2.3.2 自定义画刷QBrush用于填充封闭图形支持纯色、渐变、纹理 等填充模式void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); // 1. 纯色填充青色 QBrush brush(Qt::cyan); // 2. 渐变填充垂直渐变白色→黑色 // QBrush brush(QLinearGradient(0,0,0,200)); // brush.gradient()-setColorAt(0, Qt::white); // brush.gradient()-setColorAt(1, Qt::black); // 3. 纹理填充使用图片 // QBrush brush(QPixmap(:/texture.png)); brush.setStyle(Qt::Dense1Pattern); // 填充样式可选不同密度的图案 painter.setBrush(brush); painter.drawEllipse(QPoint(100, 100), 50, 50); }补充例子大家可以看看// widget.h #ifndef WIDGET_H #define WIDGET_H #include QWidget QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent nullptr); ~Widget(); void paintEvent(QPaintEvent* enent); private: Ui::Widget *ui; }; #endif // WIDGET_H// widget.cpp #include widget.h #include ui_widget.h #include QPainter Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui-setupUi(this); } Widget::~Widget() { delete ui; } void Widget::paintEvent(QPaintEvent *event) { (void)event; // 绘图工作就会放在这里执行 QPainter painter(this); // 画一个线段 // painter.drawLine(20,20,200,20); // painter.drawLine(QPoint(20,20),QPoint(200,20)); // painter.drawLine(20,20,300,200); // 画一个矩形 // painter.drawRect(100,100,300,200); // // 画一个圆形 // painter.drawEllipse(200,200,200,50); // 后面两个参数其实是外接矩形的宽度高度 // 绘制文本 // painter.drawText(10,100,hello); // QFont font(微软雅黑, 24); // painter.setFont(font); QPen pen; // 设置成红色的线条 pen.setColor(QColor(255,0,0)); // 设置线条的粗细 pen.setWidth(5); // 设置线条的风格 pen.setStyle(Qt::DashLine); // 让 painter 对象应用 pen 对象 painter.setPen(pen); QBrush brush; brush.setColor(QColor(0,255,0)); // brush.setStyle(Qt::SolidPattern); 填充风格 brush.setStyle(Qt::CrossPattern); painter.setBrush(brush); painter.drawEllipse(200,200,200,50); }三. 图片处理绘制、缩放与旋转Qt 提供 QPixmap、QImage、QPicture 三种图片相关绘图设备分别适用于不同场景。3.1 绘制图片QPixmapQPixmap 专为屏幕显示优化加载图片后通过drawPixmap绘制// 1. 先添加资源文件res.qrc导入图片到picture文件夹 void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); // 绘制原图左上角坐标(0,0) painter.drawPixmap(0, 0, QPixmap(:/picture/4.jpg)); // 缩放绘制左上角(300,400)宽50高60 painter.drawPixmap(300, 400, 50, 60, QPixmap(:/picture/4.jpg)); }3.2 图片平移与旋转通过translate坐标平移和rotate旋转实现图片变换注意旋转默认以原点为中心void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); QPixmap pix(:/picture/4.jpg); // 1. 平移图片原点偏移(100,100) painter.translate(100, 100); painter.drawPixmap(0, 0, pix); // 2. 旋转图片以图片中心为旋转点 painter.save(); // 保存当前状态 painter.translate(300 pix.width()/2, 100 pix.height()/2); // 平移到图片中心 painter.rotate(90); // 顺时针旋转90度 painter.translate(-(300 pix.width()/2), -(100 pix.height()/2)); // 还原原点 painter.drawPixmap(300, 100, pix); painter.restore(); // 恢复状态 }补充示例(.h这里就不再展示了跟之前的补充示例一样)#include widget.h #include ui_widget.h #include QPainter Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui-setupUi(this); } Widget::~Widget() { delete ui; } void Widget::paintEvent(QPaintEvent *event) { (void)event; QPainter painter(this); QPixmap pixmap(:/ins.png); // 基础绘制 // painter.drawPixmap(0,0,pixmap); // painter.drawPixmap(100,100,pixmap); // 图片缩放 // painter.drawPixmap(100,100,400,300,pixmap); // 图片的旋转, 本质上是把 Qpainter 对象进行了需旋转, 绘制出来的内容也就旋转了 painter.rotate(180); // 默认绕原点(0,0)旋转,所以会到屏幕外去 painter.translate(-800,-600); // 我们可以平移一下,但是由于之前旋转了所以坐标轴也变了,现在是用负的 painter.drawPixmap(100,100,400,300,pixmap); }
RELATED

相关推荐

用Python卷积神经网络实现几何形状识别:毕设实战全解析

用Python卷积神经网络实现几何形状识别:毕设实战全解析

如果把毕业论文当成一道需要反复打磨的作品,用Python做卷积神经网络(CNN)去识别几何形状,是我目前见过性价比最高、也最适合把深度学习理论落到代码的毕设方向之一。图形分类不像人脸识别、语义分割那么复杂,但麻雀虽小…

📅 2026/10/20 19:50:19
日志系统的双刃剑:如何设计一个生产环境下可动态开启且不影响实时性的 printf 重定向方案

日志系统的双刃剑:如何设计一个生产环境下可动态开启且不影响实时性的 printf 重定向方案

摘要: 日志是嵌入式调试的刚需,但日志系统设计不当会直接破坏实时性——这一点在第 2 篇《你的 printf 正在拖垮实时性》里已经用真实事故验证过。然而那篇只给出了"环形缓冲区 DMA"的骨架,生产环境的日志系统还需要解决更多问题&…

📅 2026/10/20 19:50:19
低代码平台安全盲区:AI生成代码与配置层面的隐患及防护策略

低代码平台安全盲区:AI生成代码与配置层面的隐患及防护策略

1. 低代码平台的安全困局:一个被忽视的盲区低代码平台这两年在企业数字化浪潮里跑得飞快。拖拽式界面、可视化流程编排、一键发布上线,业务人员培训三天就能搭出一个审批系统,开发周期从三个月压缩到一周。这种效率提升是实打实的&#xff0c…

📅 2026/10/20 19:45:18
MORE NEWS

更多资讯

📰

servicestack鸿蒙化适配:Flutter强类型API与消息路由跨端迁移实践

最近在做 Flutter 跨端项目时,需要把一个基于 servicestack 的旧应用底层能力迁移到鸿蒙生态里。这个库在 Dart/Flutter 端的核心价值是强类型 API 客户端和 Message-based 消息路由,它把服务端接口封装成了强类型调用,让前端不用整天拼字符串…

📰

工业组态屏选型与通讯调试全解析:从硬件到组态实战

设备运行好好的,操作工却跑过来喊“屏上数字不动了”,这是我在现场听得最多的一句话。很多人误以为“工业组态屏就是一块高级点的触摸屏”,实际上它的角色远不止显示——它是操作员与PLC之间的翻译官、数据中转站,也是整个产线的第…

📰

四款AI论文生成工具组合实战:从选题到初稿效率翻倍

写论文这件事,卡住人的往往不是查资料,而是从零到一那个从无到有的空白期。面对一屏空白文档,脑子里翻涌着几十篇文献,却不知道第一句话怎么写——这种情况我见过太多次,自己也体验过太多次。后来我开始长期试用各类AI…

📰

AI选人落地全流程:从经验直觉到数据驱动的识别体系

招聘这行做了十几年,我发现一个很扎心的现象:很多业务负责人嘴上说“我相信自己的直觉”,但年底复盘试用期淘汰率的时候,往往说不出一个像样的理由。我自己就经历过一次惨痛的复盘会——某部门一年招了10个人,3个没过试…

📰

Ubuntu+VS Code搭建C++开发环境:从工具链到调试的完整指南

1. 为什么选择 Ubuntu VS Code 搭建 C 开发环境1.1 这套组合到底解决了什么问题很多刚接触 Linux 下 C 开发的朋友,第一反应往往是"我该用哪个 IDE"。有人推荐重量级的集成环境,有人推荐纯命令行加 Vim,还有人干脆在 Windows 上写…

📰

企业微信回调验证与AES加解密:.NET开发者接入指南

接手过几个企业微信自建应用的项目,每次新人对接时几乎都会卡在同一个地方:管理后台保存“接收消息服务器”配置时提示URL验证失败,或者明明验证过了,消息却一直推送不进来。这个环节看着只是填几个参数,背后实际上是一…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬