目录

前言

绘制图形

用 QPen/QBrush 定制样式

 画笔(QPen)的样式控制

绘制文字(drawText)

​编辑绘制图片

1 基础绘制:显示原始图片

2 进阶:缩放与旋转图片

3 注意事项

总结


前言

Qt 提供的标准控件能满足大部分开发需求,但当需要个性化 UI 时,绘图 API 是实现自定义控件 / 效果的关键。本文从核心类、绘图时机到实战示例,带你快速掌握 Qt 绘图的基础逻辑。

绘图 API 的核心角色

Qt 绘图体系由 4 个核心类组成,分工明确:

类名 角色 说明
QPainter 绘者 / 画家 提供 drawXXX 方法(如 drawLine/drawRect),负责执行绘图操作。
QPaintDevice 画板 绘图的 “载体”,QWidget 是其常见子类(即可以直接在控件上绘图)。
QPen 画笔 控制绘制图形的轮廓样式(颜色、粗细、线条类型)。
QBrush 画刷 控制图形的填充样式(颜色、渐变、纹理)。

绘图的正确时机:paintEvent 事件

Qt 中绘图操作不能直接写在控件构造函数中(此时控件未完成初始化,绘图会失效),而要放在 paintEvent 事件处理函数中。

paintEvent 会在以下场景自动触发:

  1. 控件首次创建时;
  2. 控件被遮挡后解除遮挡;
  3. 窗口最小化后还原;
  4. 控件大小改变时;
  5. 主动调用 repaint()/update() 时。

绘制图形

以下示例展示如何在自定义 Widget 中重写 paintEvent,绘制线段、矩形和椭圆:

// widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    // 重写 paintEvent 事件处理函数
    void paintEvent(QPaintEvent *event) override;
};
#endif // WIDGET_H
// widget.cpp
#include "widget.h"
#include <QPainter>
#include <QPoint>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    setFixedSize(400, 400); // 设置控件大小
}

Widget::~Widget()
{
}

void Widget::paintEvent(QPaintEvent *event)
{
    (void)event; // 忽略事件参数

    // 1. 创建 QPainter 对象,指定“画板”为当前 Widget
    QPainter painter(this);

    // 2. 绘制线段
    painter.drawLine(20, 20, 200, 20); // 从 (20,20) 到 (200,20)
    painter.drawLine(QPoint(20, 100), QPoint(200, 100)); // 用 QPoint 传坐标

    // 3. 绘制矩形(x,y,宽度,高度)
    painter.drawRect(100, 100, 300, 200);

    // 4. 绘制椭圆(x,y,宽度,高度)
    painter.drawEllipse(200, 200, 200, 50);
}

用 QPen/QBrush 定制样式

通过 QPen 和 QBrush,可以给图形添加轮廓和填充效果:

void Widget::paintEvent(QPaintEvent *event)
{
    (void)event;
    QPainter painter(this);

    // 1. 设置画笔(红色、2px 实线)
    QPen pen;
    pen.setColor(Qt::red);
    pen.setWidth(2);
    pen.setStyle(Qt::SolidLine);
    painter.setPen(pen);

    // 2. 设置画刷(蓝色填充)
    QBrush brush;
    brush.setColor(Qt::blue);
    brush.setStyle(Qt::SolidPattern);
    painter.setBrush(brush);

    // 3. 绘制带样式的矩形
    painter.drawRect(50, 50, 200, 150);
 画笔(QPen)的样式控制

QPen 不仅能设置颜色、粗细,还能控制线条样式(如实线、虚线),常用样式包括:

样式常量 效果描述
Qt::SolidLine 实线(默认)
Qt::DashLine 虚线(短横线)
Qt::DotLine 点线
Qt::DashDotLine 点划线(短横 + 点)
Qt::DashDotDotLine 双点划线

结合QBrush使用

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}
void Widget::paintEvent(QPaintEvent* event)
{
    (void)event; // 忽略事件参数,避免编译器警告

    // 1. 创建画家对象,指定绘图载体为当前Widget
    QPainter painter(this);

    // 2. 创建并设置画刷(绘制图形前设置)
    QBrush brush;
    brush.setColor(QColor(100, 0, 100)); // RGB 紫色
    brush.setStyle(Qt::CrossPattern);    // 十字交叉填充样式
    painter.setBrush(brush);             // 将画刷应用到画家

    // 3. 绘制矩形(此时会使用上述画刷填充)
    painter.drawRect(100, 100, 300, 200);
}

Widget::~Widget()
{
    delete ui;
}

效果:

绘制文字(drawText

通过 QPainter::drawText 可在控件上绘制文字,需注意坐标的含义:

// 创建字体:字体为“微软雅黑”,大小20
QFont font("微软雅黑", 20);
// 将字体设置到画家对象中
painter.setFont(font);
painter.drawText(0, 100, "hello");
  • 横坐标 0:文字最左侧的位置;
  • 纵坐标 100:文字的基线(baseline)位置(即文字底部对齐的基准线,不是文字的顶部 / 底部坐标)。


绘制图片

在 Qt 中,QPixmap 是专门用于在屏幕上显示图像的类,对显示优化友好。通过 QPainter::drawPixmap 方法可以将图片绘制到控件上,支持基础显示、缩放、旋转等操作。

1 基础绘制:显示原始图片

最基本的图片绘制步骤如下:

void Widget::paintEvent(QPaintEvent *event)
{
    (void)event;
    QPainter painter(this);

    // 1. 加载图片(路径需根据实际图片位置调整)
    QPixmap pixmap(":/images/cat.jpg"); // 假设图片放在资源文件中

    // 2. 绘制图片:左上角坐标 (50, 50),显示原始大小
    painter.drawPixmap(50, 50, pixmap);
}

关键说明

  • 图片路径:若图片在项目目录下,可直接写相对路径(如 "./cat.jpg");若添加到 Qt 资源文件(.qrc),需用资源路径(如 ":/images/cat.jpg");
  • 坐标含义:drawPixmap(50, 50, pixmap) 表示图片左上角对齐控件的 (50, 50) 坐标,图片尺寸保持原始大小。

2 进阶:缩放与旋转图片

QPixmap 支持绘制时调整图片大小,结合 QPainter 的变换功能还能实现旋转效果。

示例:缩放并旋转图片

void Widget::paintEvent(QPaintEvent *event)
{
    (void)event;
    QPainter painter(this);

    // 加载图片
    QPixmap pixmap(":/images/cat.jpg");
    if (pixmap.isNull()) { // 检查图片是否加载成功
        painter.drawText(100, 100, "图片加载失败");
        return;
    }

    // 1. 缩放绘制:将图片缩放到 (300x200) 尺寸,左上角坐标 (100, 100)
    painter.drawPixmap(100, 100, 300, 200, pixmap);

    // 2. 旋转绘制:先保存画家状态,避免影响后续绘图
    painter.save(); 

    // 旋转30度(原点默认在控件左上角,旋转会导致图片偏移,需调整坐标)
    painter.rotate(30); 
    // 平移坐标,使旋转中心对准目标位置(避免图片超出可视区域)
    painter.translate(400, -200); 
    // 绘制旋转后的图片(尺寸 200x150)
    painter.drawPixmap(0, 0, 200, 150, pixmap);

    // 恢复画家状态(清除旋转、平移等变换)
    painter.restore(); 
}

核心技巧

  • 缩放:drawPixmap(x, y, width, height, pixmap) 中,width 和 height 为目标尺寸,图片会自动拉伸 / 压缩适配;
  • 旋转:通过 painter.rotate(角度) 实现,旋转原点默认是控件左上角,因此旋转后常需用 translate(x, y) 调整坐标,避免图片偏移到可视区域外;
  • 状态保存:save() 和 restore() 用于隔离不同绘图操作的状态(如旋转、画笔样式),防止相互干扰。

3 注意事项

  1. 图片格式QPixmap 支持常见格式(JPG、PNG、BMP 等),但加载失败时 isNull() 会返回 true,建议添加判断;
  2. 资源管理:大型图片建议通过资源文件(.qrc)管理,避免路径依赖问题;
  3. 性能QPixmap 适合显示静态图片,若需频繁修改像素(如滤镜处理),建议先用 QImage 处理后再转为 QPixmap 显示。

通过 QPixmap 和 QPainter 的结合,可轻松实现图片的各种显示效果,是自定义 UI 中展示图像的核心工具。

总结

Qt 绘图 API 是自定义控件的基础,核心要点是:

  • 核心类QPainter(绘图)、QPaintDevice(载体)、QPen(轮廓)、QBrush(填充);
  • 绘图时机:必须在 paintEvent 中执行,自动响应控件状态变化;
  • 实用场景:当标准控件无法满足需求时(如自定义仪表盘、特殊形状按钮),通过绘图 API 实现个性化效果。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐