本文最后更新于 2025-02-20,学习久了要注意休息哟

第一章 绘图基础

1.1 绘图简介

1.1.1 绘图在 Qt 中的作用

  • 自定义控件:Qt 提供了强大的绘图功能,允许开发者创建具有定制化外观和行为的控件。这对于绘制复杂的图形和交互式组件(如自定义按钮、滑块等)非常有用。
  • 图形编辑器:Qt 的绘图框架使得开发图形编辑器、绘图程序变得简单。比如:绘制线条、矩形、圆形、自由图形等,以及处理鼠标和键盘输入事件。
  • 游戏开发:对于游戏开发中的图形渲染,Qt 提供了强大的绘制支持,允许开发者进行快速的界面绘制和动画效果实现。

1.1.2 Qt 的绘图框架

  • QPainter:是 Qt 中绘制图形的核心类,提供了大量的绘图方法来绘制基本形状、文本和图像。
  • QWidget 的关系QWidget 是所有 Qt 控件的基类,所有控件的绘制操作都是通过重写 paintEvent() 方法来实现的,通常在 paintEvent() 中会创建一个 QPainter 对象来完成绘图任务。
  • 绘图设备QPainter 可以在不同的设备上绘制图形,包括窗口、图像、打印机等。不同的绘图设备有不同的实现方式,但它们都支持 QPainter。

1.2 QPainter 基础

1.2.1 QPainter 类的简介

  • 作用QPainter 类提供了在不同绘图设备上绘制图形的方法。它是 Qt 的绘图核心,允许开发者绘制点、线、矩形、圆形、文本等。
  • 常用方法:
    • begin(): 开始绘图,指定绘图设备。
    • end(): 结束绘图操作,释放资源。
    • setPen(): 设置画笔,用于绘制线条和轮廓。
    • setBrush(): 设置画刷,用于填充图形。
    • drawLine(): 绘制直线。
    • drawRect(): 绘制矩形。
    • drawEllipse(): 绘制椭圆或圆形。
    • drawText(): 绘制文本。
    • setRenderHint(): 设置渲染提示(如抗锯齿)。

1.2.2 创建 QPainter 对象的方式

创建和初始化 QPainter:

paintEvent() 中使用:大多数情况下,我们会在重写的 paintEvent() 方法中创建 QPainter 对象。paintEvent() 会自动接收到一个 QPaintEvent 事件,作为绘图事件的触发函数。

void MyWidget::paintEvent(QPaintEvent *event) {
    QPainter painter(this);  // 创建 QPainter 对象
    painter.setRenderHint(QPainter::Antialiasing);  // 启用抗锯齿
    painter.drawRect(10, 10, 100, 100);  // 绘制矩形
}

绘制其他设备:如在 QImageQPixmap 上绘图时,需要在构造函数中指定相应的设备。

QImage image(500, 500, QImage::Format_ARGB32);
QPainter painter(&image);
painter.setPen(Qt::red);
painter.drawLine(0, 0, 500, 500);

1.2.3 QPainter 常用的绘制操作

  • 绘制线条

    drawLine()
    

    方法绘制直线。

    painter.drawLine(10, 10, 100, 100);  // 绘制从 (10, 10) 到 (100, 100) 的线段
    
  • 绘制矩形

    drawRect()
    

    方法绘制矩形。

    painter.drawRect(10, 10, 100, 50);  // 绘制一个宽 100,高 50 的矩形
    
  • 绘制圆形/椭圆

    drawEllipse()
    

    方法绘制圆形或椭圆。

    painter.drawEllipse(10, 10, 100, 100);  // 绘制一个圆形
    
  • 绘制路径

    QPainterPath
    

    类绘制复杂的图形(如贝塞尔曲线)。

    QPainterPath path;
    path.moveTo(50, 50);
    path.lineTo(100, 100);
    painter.drawPath(path);
    
  • 绘制文本

    drawText()
    

    方法绘制文本。

    painter.drawText(10, 10, "Hello, Qt!");  // 绘制文本
    

1.2.4 使用 QPainter::begin() 和 QPainter::end()

  • begin()

    :在绘制之前调用

    begin()
    

    ,用于初始化绘图设备。

    QPainter painter;
    painter.begin(this);  // 在控件上开始绘制
    
  • end()

    :绘制完成后调用

    end()
    

    ,用于清理资源。

    painter.end();  // 结束绘制
    

1.3 设备坐标系

1.3.1 坐标系的基本概念

  • 原点:坐标系的起始点,通常为 (0, 0)
  • 方向:在二维坐标系中,x轴从左到右为正方向,y轴从上到下为正方向。
  • 单位:在屏幕显示设备中,单位通常是像素,代表显示器的分辨率。

1.3.2 QPainter 和设备坐标系的关系

  • QWidget 坐标系:默认情况下,QPainter 使用控件的坐标系(即 QWidget 的坐标系)进行绘制。绘制的坐标原点位于控件的左上角。
  • QPixmap 和 QImage 坐标系:对于图像设备,QPainter 会使用图像的坐标系来绘制,原点通常是图像的左上角。

1.3.3 使用 QPainter::setTransform() 操作坐标变换

  • 坐标变换

    :可以通过

    QPainter::setTransform()
    

    来对绘图坐标进行缩放、旋转、平移等操作。

    • 平移:移动坐标系的位置。
    painter.translate(50, 50);  // 将坐标系平移到 (50, 50)
    
    • 旋转:绕原点旋转坐标系。
    painter.rotate(45);  // 将坐标系顺时针旋转 45 度
    
    • 缩放:对坐标系进行缩放。
    painter.scale(2.0, 2.0);  // 将坐标系缩放 2 倍
    
  • QTransformQPainter::setTransform() 接受一个 QTransform 对象,QTransform 用于管理坐标变换。

第二章 绘制前的准备

在进行绘图之前,首先需要创建一个 QPainter 对象,并通过 begin()end() 方法来控制绘图的开始和结束。我们通常会在控件的 paintEvent 方法中进行绘制。

2.1 画笔

2.1.1 画笔设置

QPen::QPen
QPen::QPen(const QColor &color)
    。。。

2.1.2 画笔宽度

// 获取画笔的宽度(整数类型)
int width() const;

// 设置画笔的宽度
void setWidth(int width);

// 获取画笔的宽度(浮点类型)
qreal widthF() const;

// 设置画笔的宽度(浮点类型)
void setWidthF(qreal width);

2.1.3 画笔颜色

// 获取画笔的颜色
QColor color() const;

// 设置画笔的颜色
void setColor(const QColor &color);

2.1.4 画笔样式

// 获取画笔的样式
Qt::PenStyle style() const;

// 设置画笔的样式
void setStyle(Qt::PenStyle style);

image-20250219224415340

2.1.4 连接

// 获取和设置画笔的 Join 样式
Qt::PenJoinStyle joinStyle() const;
void setJoinStyle(Qt::PenJoinStyle style)

image-20250219224524400

2.1.5 末端

// 获取和设置画笔的 Cap 样式
Qt::PenCapStyle capStyle() const;
void setCapStyle(Qt::PenCapStyle style)

image-20250219224604820

2.1.6 示例程序

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

    // 创建一个红色画笔,宽度为 3,实线
    QPen pen(Qt::red, 3, Qt::SolidLine);
    painter.setPen(pen);  // 设置画笔

    // 绘制一条直线
    painter.drawLine(10, 10, 200, 200);

    // 修改画笔属性为蓝色,虚线
    pen.setColor(Qt::blue);
    pen.setStyle(Qt::DashLine);
    painter.setPen(pen);  // 更新画笔

    // 绘制一条虚线
    painter.drawLine(10, 200, 200, 10);
}

2.2 画刷

2.2.1 画刷颜色

// 获取和设置画刷的颜色
const QColor &color() const
void setColor(const QColor &color)

2.2.2 样式

// 获取和设置画刷的样式
Qt::BrushStyle style() const
void setStyle(Qt::BrushStyle style)

image-20250219224840774

第三章 基本图形

3.1 点与线

在 Qt 中,点和线是最基本的图形元素,通常用于构建更复杂的图形。QPainter 提供了多种方法来绘制点、线和与之相关的图形。

3.1.1 点绘制

QPainter 提供了 drawPoint() 方法用于绘制单个点。

API

// 绘制一个点
// 绘制一个指定位置的点。
void QPainter::drawPoint(int x, int y);
// 绘制一个指定位置的点,使用 QPoint 对象表示坐标。
void QPainter::drawPoint(const QPoint &point);

示例程序

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

    // 设置画笔为蓝色,宽度为3
    QPen pen(Qt::blue);
    pen.setWidth(3);
    painter.setPen(pen);

    // 绘制一条从(50, 50)到(200, 200)的线
    painter.drawLine(50, 50, 200, 200);
}

3.1.2 线绘制

API

// 绘制一条线

// 绘制一条从 (x1, y1) 到 (x2, y2) 的直线。
void QPainter::drawLine(int x1, int y1, int x2, int y2);
// 绘制通过 QLine 对象指定的线。
void QPainter::drawLine(const QLine &line);
// 绘制连接 p1 和 p2 的直线。
void QPainter::drawLine(const QPoint &p1, const QPoint &p2);

示例程序

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

    // 设置画笔为蓝色,宽度为3
    QPen pen(Qt::blue);
    pen.setWidth(3);
    painter.setPen(pen);

    // 绘制一条从(50, 50)到(200, 200)的线
    painter.drawLine(50, 50, 200, 200);
}

3.1.3 示例程序

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

    // 绘制多个点
    QPen pen1(Qt::green);
    pen1.setWidth(4);
    painter.setPen(pen1);
    painter.drawPoint(50, 50);
    painter.drawPoint(150, 150);
    painter.drawPoint(250, 250);

    // 绘制一条线
    QPen pen2(Qt::blue);
    pen2.setWidth(2);
    painter.setPen(pen2);
    painter.drawLine(50, 50, 250, 250);  // 绿色点到蓝色线的连接

    // 绘制另一条线
    QPen pen3(Qt::red);
    pen3.setWidth(5);
    pen3.setStyle(Qt::DashLine);  // 设置虚线
    painter.setPen(pen3);
    painter.drawLine(150, 150, 50, 250);  // 红色虚线
}

3.2 多边形与多段线

在 Qt 中,绘制多边形和多段线是常见的图形操作。QPainter 提供了相关的 API 来绘制这些复杂的图形。多边形是由一系列连续的直线段围成的闭合区域,而多段线是由多个直线段组成,但不一定是闭合的。

3.2.1 多边形绘制

QPainter 提供了 drawPolygon() 方法来绘制多边形。QPolygon 是一个由多个点组成的容器,通常用来表示多边形的顶点。

API

// 绘制多边形
void QPainter::drawPolygon(const QPoint *points, int pointCount);
void QPainter::drawPolygon(const QPolygon &polygon);

示例程序

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

    // 设置画笔为蓝色
    QPen pen(Qt::blue);
    pen.setWidth(3);
    painter.setPen(pen);

    // 定义一个多边形
    QPoint points[4] = { QPoint(50, 50), QPoint(150, 50), QPoint(150, 150), QPoint(50, 150) };
    painter.drawPolygon(points, 4);  // 绘制一个四边形
}

3.2.2 多段线绘制

多段线绘制使用 QPainterdrawPolyline() 方法。多段线由多个连续的线段组成,但它不要求形成一个封闭的区域。

API

// 绘制多段线  

// 传入一个点数组和点的数量来绘制多边形。
void QPainter::drawPolyline(const QPoint *points, int pointCount);
// 传入一个 QPolygon 对象来绘制多边形。
void QPainter::drawPolyline(const QPolygon &polyline);

示例程序

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

    // 设置画笔为红色
    QPen pen(Qt::red);
    pen.setWidth(2);
    painter.setPen(pen);

    // 定义多段线的点
    QPoint points[5] = { QPoint(50, 50), QPoint(100, 100), QPoint(150, 50), QPoint(200, 100), QPoint(250, 50) };
    painter.drawPolyline(points, 5);  // 绘制多段线
}

3.2.3 示例程序

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

    // 设置画笔为红色
    QPen pen(Qt::red);
    pen.setWidth(2);
    painter.setPen(pen);

    // 定义多段线的点
    QPoint points[5] = { QPoint(50, 50), QPoint(100, 100), QPoint(150, 50), QPoint(200, 100), QPoint(250, 50) };
    painter.drawPolyline(points , 5);  // 绘制多段线
}

3.3 矩形与圆角矩形

3.3.1 矩形

API

// 绘制矩形
// 指定矩形的左上角位置(x, y)和矩形的宽度和高度
void QPainter::drawRect(int x, int y, int width, int height);
// 使用 QRect 对象来定义矩形的区域
void QPainter::drawRect(const QRect &rect);

示例程序

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

    // 设置画笔颜色
    QPen pen(Qt::blue);
    pen.setWidth(3);
    painter.setPen(pen);

    // 绘制矩形
    painter.drawRect(50, 50, 200, 100);  // 使用左上角坐标和宽高绘制矩形

    // 或者使用 QRect 绘制矩形
    QRect rect(50, 200, 200, 100);
    painter.drawRect(rect);  // 使用 QRect 绘制矩形
}

3.3.2 圆角矩形

API

// 绘制圆角矩形
// 指定圆角矩形的矩形区域、宽度、高度以及水平和垂直方向的圆角半径
void QPainter::drawRoundedRect(int x, int y, int width, int height, qreal xRadius, qreal yRadius);
// 使用 QRect 对象来指定矩形的区域,同时指定圆角半径
void QPainter::drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius);

示例程序

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

    // 设置画笔为红色
    QPen pen(Qt::red);
    pen.setWidth(2);
    painter.setPen(pen);

    // 绘制圆角矩形
    painter.drawRoundedRect(50, 50, 200, 100, 20, 20);  // 使用左上角坐标和宽高以及圆角半径绘制圆角矩形

    // 或者使用 QRect 绘制圆角矩形
    QRect rect(50, 200, 200, 100);
    painter.drawRoundedRect(rect, 20, 20);  // 使用 QRect 绘制圆角矩形
}

3.4 椭圆与圆形

3.4.1 椭圆

API

// 绘制椭圆
// 根据指定的矩形位置和宽高来绘制椭圆
void QPainter::drawEllipse(int x, int y, int width, int height);
// 使用 QRect 对象来指定椭圆的区域。
void QPainter::drawEllipse(const QRect &rect);

示例程序

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

    // 设置画笔颜色
    QPen pen(Qt::green);
    pen.setWidth(2);
    painter.setPen(pen);

    // 绘制椭圆
    painter.drawEllipse(50, 50, 200, 100);  // 绘制一个宽200、高100的椭圆

    // 使用 QRect 绘制椭圆
    QRect rect(50, 200, 200, 100);
    painter.drawEllipse(rect);  // 使用 QRect 绘制椭圆
}

3.4.2 圆形

API

// 绘制圆形
void QPainter::drawEllipse(int x, int y, int diameter, int diameter);
void QPainter::drawEllipse(const QRect &rect);

示例程序

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

    // 设置画笔颜色
    QPen pen(Qt::blue);
    pen.setWidth(3);
    painter.setPen(pen);

    // 绘制圆形
    painter.drawEllipse(50, 50, 100, 100);  // 绘制一个半径为50的圆形

    // 使用 QRect 绘制圆形
    QRect rect(50, 200, 100, 100);  // 使用一个正方形的 QRect 绘制圆形
    painter.drawEllipse(rect);  // 使用 QRect 绘制圆形
}

3.6 路径与圆弧

3.6.1 路径

API

// 将绘制位置移动到指定坐标 (x, y),并且不画线。
QPainterPath::moveTo(qreal x, qreal y)

// 从当前位置画一条直线到 (x, y)。
QPainterPath::lineTo(qreal x, qreal y)

// 绘制圆弧,从 startAngle 开始,跨越 spanAngle 度数,圆弧的外接矩形由 rect 定义。
QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal spanAngle)

// 绘制三次贝塞尔曲线。
QPainterPath::cubicTo(qreal x1, qreal y1, q2, q2, q3, q3)

示例程序

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

    // 设置画笔颜色
    QPen pen(Qt::green);
    pen.setWidth(2);
    painter.setPen(pen);

    // 创建路径
    QPainterPath path;

    // 使用 moveTo 移动到起点
    path.moveTo(50, 50);

    // 使用 lineTo 绘制直线
    path.lineTo(150, 50); // 直线到 (150, 50)

    // 使用 arcTo 绘制圆弧
    path.arcTo(50, 50, 100, 100, 0, 180); // 从 (50, 50) 绘制半圆

    // 使用 cubicTo 绘制三次贝塞尔曲线
    path.cubicTo(75, 150, 125, 150, 150, 100); // 三次贝塞尔曲线

    // 绘制路径
    painter.drawPath(path);
}

3.6.2 圆弧

API

// 绘制圆弧,从 startAngle 开始,跨越 spanAngle 度数,圆弧的外接矩形由 rect 定义。
QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal spanAngle)

    @ rect:圆弧的外接矩形,决定圆弧的大小和位置。
    @ startAngle:圆弧的起始角度,以 1/16 度为单位(360 度 = 5760)。
    @ spanAngle:圆弧的跨越角度,以 1/16 度为单位,表示圆弧的跨度。

示例程序

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

    // 设置画笔颜色
    QPen pen(Qt::blue);
    pen.setWidth(2);
    painter.setPen(pen);

    // 创建路径
    QPainterPath path;

    // 绘制圆弧,外接矩形 (50, 50, 100, 100),从 0 度开始,跨越 90 度
    path.arcTo(50, 50, 100, 100, 0, 90); // 绘制 90 度的圆弧

    // 绘制路径
    painter.drawPath(path);
}

3.5 圆饼与弦图

3.5.1 圆饼

3.5.2 弦图

第四章 图像与文本

4.1 文本

4.2 图像

4.3 平移、旋转、缩放