Cx330❀头像
深入浅出 Qt 绘图机制:从 QPainter 到四大图像类解析封面图

深入浅出 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 绘制图片(QPixmap)

3.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半径30,y半径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半径30,y半径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 绘制图片(QPixmap)

QPixmap 专为屏幕显示优化,加载图片后通过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);

}

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/yhrxh_ymq/article/details/167127120

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--