QtGUI模块功能详细说明,图形绘制与渲染(二)

目录

一. 窗口和屏幕管理

二. 绘图和渲染

1、基础概念与核心

1.1、2D 绘图与渲染概述

1.2、核心绘图引擎:QPainter

1.3、绘图设备:QPaintDevice

2、样式与填充

2.1、线条样式:QPen

2.2、填充样式:QBrush

2.3、渐变填充:QGradient

3、复杂图形与区域

3.1、复杂路径绘制:QPainterPath

3.2、2D 区域:QRegion

4、变换与坐标系统

4.1、2D 变换:QTransform

4.2、高级变换与坐标(常用于 OpenGL 相关)

5、与 UI 集成:在控件上绘图说明

5.1、QWidget 的 paintEvent()

5.2、在 paintEvent() 中使用 QPainter

5.3、更新控件:update()、repaint()

5.4、双缓冲绘图以减少闪烁

三. 图像处理

四. 字体和文本

五. 事件和输入处理

六. OpenGL 和硬件加速

七. 颜色和外观

八. 图标和光标

九. 平台和渲染后端

十. 国际化(GUI 相关)


一. 窗口和屏幕管理

请跳转章节,此处不再重复:QtGUI模块功能详细说明,窗口和屏幕管理(一)

二. 绘图和渲染

1、基础概念与核心

1.1、2D 绘图与渲染概述

2D 绘图是指在二维平面(通常以像素为单位)上绘制图形、图像和文本的过程。Qt 的 2D 绘图系统以 QPainter 为核心,结合 QPaintDevice 及其派生类(如 QWidget、QImage、QPixmap)实现灵活的绘图功能。

渲染流程

  • 选择绘图设备:确定绘图目标(如 QWidget、QImage、QPixmap)。

  • 初始化 QPainter:创建 QPainter 对象并绑定到绘图设备。

  • 执行绘制操作:调用 QPainter 的方法绘制点、线、形状、图像或文本。

  • 结束绘制:完成绘制并释放资源。

  • 显示或保存:将结果显示在屏幕上或保存为文件。

1.2、核心绘图引擎:QPainter

QPainter 是 Qt 2D 绘图的核心类,负责执行所有绘制操作。它通过与 QPaintDevice 交互,将图形命令渲染到目标设备上。

1.2.1、QPainter 的生命周期

  • 初始化:QPainter 必须绑定到一个 QPaintDevice 才能工作。

    • 通过调用 begin(QPaintDevice*) 绑定。

    • QPainter 对象也可以在构造时直接绑定设备。

  • 绘制:在 begin() 和 end() 之间调用绘制方法。

  • 结束:调用 end() 释放资源,完成绘制。

  • 构造时绑定设备 → 隐式调用 begin() → 绘制内容 → 析构时隐式调用 end()

1.2.2、基本用法

  • 创建 QPainter:手动创建并绑定、构造函数绑定。

  • 设置画笔和画刷:

    • 画笔(QPen):控制线条的颜色、宽度、样式(如实线、虚线)。

    • 画刷(QBrush):控制填充的颜色、样式(如纯色、渐变、图案)。

  • 启用抗锯齿:减少或消除图形边缘出现的锯齿状阶梯现象

1.2.3、绘制基本图形

  • 点 (Point):使用 drawPoint() 方法绘制单个点。

  • 线 (Line):使用 drawLine() 方法绘制两点之间的直线段。

  • 折线 (Polyline):使用 drawPolyline() 方法绘制由多个连接的线段组成的折线。

  • 矩形 (Rectangle):使用 drawRect() 方法绘制矩形。可以指定左上角坐标和宽高,或指定两个对角点。

  • 绘制圆角矩形 (Rounded Rectangle),使用 drawRoundedRect()。

  • 椭圆 (Ellipse):使用 drawEllipse() 方法绘制椭圆。通常指定外切矩形来定义椭圆的位置和大小。

  • 圆弧 (Arc):使用 drawArc() 方法绘制椭圆的一部分,即圆弧。需要指定外切矩形、起始角度和跨越角度。

  • 弦 (Chord):使用 drawChord() 方法绘制椭圆的一个部分,由圆弧及其两个端点连成的直线(弦)围成。需要指定外切矩形、起始角度和跨越角度。

  • 扇形 (Pie):使用 drawPie() 方法绘制椭圆的一个扇形区域,由圆心到圆弧两个端点的半径和圆弧围成。需要指定外切矩形、起始角度和跨越角度。

  • 多边形 (Polygon):使用 drawPolygon() 方法绘制封闭的多边形。需要提供多边形各个顶点的坐标。

  • 路径 (Path):使用 drawPath() 方法绘制由 QPainterPath 对象定义的任意复杂图形。包含直线、曲线(贝塞尔曲线)、圆弧等多种元素,并且可以组合它们来构建复杂的形状。

1.2.4、绘制图像

  • QImage:使用drawImage(),适合像素级操作,CPU 渲染,常用于图像处理。

  • QPixmap:使用drawPixmap(),优化为屏幕显示,GPU 加速,适合 GUI 渲染。

1.2.4、绘制文本

  • 绘制简单文本:使用drawText()绘制文本,使用setFont()设置字体。

  • 文本对齐与排版:使用drawText()绘制文本,使用QRect现在对齐,对齐方式包括

    • Qt::AlignLeft

    • Qt::AlignRight

    • Qt::AlignTop

    • Qt::AlignBottom

1.2.5、保存与恢复绘图状态

QPainter 支持状态栈,用于保存和恢复绘图设置(如画笔、画刷、变换矩阵等)

  • 保存状态:save() 将当前状态压入栈。

  • 恢复状态:restore() 恢复最近保存的状态。

  • 注:save() 和 restore() 必须配对使用,避免栈溢出或状态丢失。

1.2.6、示例代码

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QColor>
#include <QFont>
#include <QPixmap>
#include <QImage>
#include <QPainterPath>
#include <QPolygon>
#include <QRect>
#include <QPoint>
#include <QPointF>
#include <QPaintEvent>


class DrawingWidget : public QWidget
{
    Q_OBJECT

public:

    DrawingWidget(QWidget *parent = nullptr)
        : QWidget(parent)
    {
        setWindowTitle("QPainter 核心功能示例 (C++)");
        setFixedSize(800, 600);

        // 创建一个简单的 QImage 和 QPixmap 用于演示
        sampleImage = QImage(100, 50, QImage::Format_RGB32);
        sampleImage.fill(Qt::blue); // 填充蓝色

        samplePixmap = QPixmap(100, 50);
        samplePixmap.fill(Qt::green); // 填充绿色
    }

    ~DrawingWidget() override = default;

protected:
    // 重写 paintEvent 方法
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event); // 避免编译器警告,event 在此例中未使用

        //===============================================================
        // 1.2.1、QPainter 的生命周期 - 在 paintEvent 中自动处理 begin/end
        //===============================================================

        // QPainter 对象在构造时直接绑定设备 (this 指向 DrawingWidget)
        QPainter painter(this);

        //===============================================================
        // 1.2.2、基本用法 - 设置画笔、画刷、启用抗锯齿
        //===============================================================

        // 启用抗锯齿
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.setRenderHint(QPainter::SmoothPixmapTransform, true); // 平滑缩放图片

        // 设置默认画笔 (黑色,宽度2)
        QPen defaultPen(Qt::black, 2, Qt::SolidLine);
        painter.setPen(defaultPen);

        // 设置默认画刷 (无填充)
        QBrush defaultBrush(Qt::NoBrush);
        painter.setBrush(defaultBrush);

        int y_offset = 20; // 起始绘制的 Y 坐标

        //===============================================================
        // --- 绘制基本图形 ---
        //===============================================================

        // 1.2.3、绘制基本图形 - 点
        painter.setPen(QPen(Qt::red, 5, Qt::SolidLine, Qt::RoundCap)); // 粗点
        painter.drawPoint(50, y_offset);
        painter.setFont(QFont("Arial", 8));
        painter.setPen(Qt::black);
        painter.drawText(60, y_offset + 5, "drawPoint");
        y_offset += 20;

        // 1.2.3、绘制基本图形 - 线
        painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine));
        painter.drawLine(50, y_offset, 150, y_offset + 30);
        painter.drawText(160, y_offset + 30, "drawLine");
        y_offset += 40;

        // 1.2.3、绘制基本图形 - 折线
        painter.setPen(QPen(Qt::darkGreen, 2, Qt::DashLine));
        QVector<QPoint> polylinePoints; // 使用QVector存储点
        polylinePoints << QPoint(50, y_offset) << QPoint(100, y_offset + 20) << QPoint(50, y_offset + 40) << QPoint(100, y_offset + 60);
        painter.drawPolyline(QPolygon(polylinePoints));
        painter.setPen(Qt::black);
        painter.drawText(110, y_offset + 60, "drawPolyline");
        y_offset += 70;

        // 1.2.3、绘制基本图形 - 矩形 (实心填充)
        painter.setPen(QPen(Qt::black, 1));
        painter.setBrush(QBrush(Qt::yellow));
        painter.drawRect(50, y_offset, 80, 50);
        painter.setBrush(defaultBrush); // 恢复无填充
        painter.setPen(Qt::black);
        painter.drawText(140, y_offset + 30, "drawRect (Filled)");
        y_offset += 60;

        // 1.2.3、绘制基本图形 - 圆角矩形 (轮廓)
        painter.setPen(QPen(Qt::magenta, 2));
        painter.drawRoundedRect(50, y_offset, 80, 50, 15, 15); // x, y, w, h, xRadius, yRadius
        painter.setPen(Qt::black);
        painter.drawText(140, y_offset + 30, "drawRoundedRect");
        y_offset += 60;

        // 1.2.3、绘制基本图形 - 椭圆 (实心填充)
        painter.setPen(QPen(Qt::black, 1));
        painter.setBrush(QBrush(Qt::cyan));
        painter.drawEllipse(50, y_offset, 80, 50);
        painter.setBrush(defaultBrush);
        painter.setPen(Qt::black);
        painter.drawText(140, y_offset + 30, "drawEllipse (Filled)");
        y_offset += 60;

        // 1.2.3、绘制基本图形 - 圆弧, 弦, 扇形 (基于同一个椭圆)
        QRect arcRect(50, y_offset, 100, 100);
        painter.setPen(QPen(Qt::red, 2));
        painter.drawArc(arcRect, 0 * 16, 90 * 16); // 从0度开始,跨越90度 (Qt角度单位为1/16度)
        painter.setPen(Qt::black);
        painter.drawText(160, y_offset + 20, "drawArc");

        painter.setPen(QPen(Qt::blue, 2));
        painter.drawChord(arcRect, 90 * 16, 90 * 16); // 从90度开始,跨越90度
        painter.setPen(Qt::black);
        painter.drawText(160, y_offset + 50, "drawChord");

        painter.setPen(QPen(Qt::darkYellow, 2));
        painter.setBrush(QBrush(Qt::lightGray));
        painter.drawPie(arcRect, 180 * 16, 90 * 16); // 从180度开始,跨越90度
        painter.setBrush(defaultBrush);
        painter.setPen(Qt::black);
        painter.drawText(160, y_offset + 80, "drawPie (Filled)");

        y_offset += 110;

        // 1.2.3、绘制基本图形 - 多边形 (实心填充)
        painter.setPen(QPen(Qt::darkMagenta, 2));
        painter.setBrush(QBrush(Qt::darkCyan));
        QVector<QPoint> polygonPoints;
        polygonPoints << QPoint(50, y_offset) << QPoint(80, y_offset + 40) << QPoint(20, y_offset + 40);
        painter.drawPolygon(QPolygon(polygonPoints));
        painter.setBrush(defaultBrush);
        painter.setPen(Qt::black);
        painter.drawText(90, y_offset + 20, "drawPolygon (Filled)");
        y_offset += 50;

        // 1.2.3、绘制基本图形 - 路径 (QPainterPath)
        painter.setPen(QPen(Qt::darkRed, 2));
        painter.setBrush(QBrush(Qt::yellow));
        QPainterPath path;
        path.moveTo(200, 50);
        path.cubicTo(250, 10, 300, 90, 350, 50); // 立方贝塞尔曲线
        path.addEllipse(300, 60, 50, 30); // 添加一个椭圆到路径
        painter.drawPath(path); // 绘制并填充路径
        painter.setBrush(defaultBrush);
        painter.setPen(Qt::black);
        painter.drawText(360, 50, "drawPath (Cubic Bezier + Ellipse)");


        //===============================================================
        // --- 绘制图像 ---
        //===============================================================
        int y_offset_image = 160;
        int x_offset_image = 200;

        // 1.2.4、绘制图像 - QImage
        painter.drawImage(x_offset_image, y_offset_image, sampleImage);
        painter.drawText(x_offset_image + sampleImage.width() + 10, y_offset_image + 20, "drawImage (QImage)");
        y_offset_image += sampleImage.height() + 20;

        // 1.2.4、绘制图像 - QPixmap
        painter.drawPixmap(x_offset_image, y_offset_image, samplePixmap);
        painter.drawText(x_offset_image + samplePixmap.width() + 10, y_offset_image + 20, "drawPixmap (QPixmap)");
        y_offset_image += samplePixmap.height() + 20;

        // --- 绘制文本 ---
        int y_offset_text = 300;
        int x_offset_text = 200;

        // 1.2.4、绘制文本 - 简单文本
        painter.setPen(Qt::black);
        painter.setFont(QFont("Times", 12, QFont::Bold));
        painter.drawText(x_offset_text, y_offset_text, "Hello QPainter Text!");
        y_offset_text += 30;

        // 1.2.4、绘制文本 - 文本对齐与排版
        QRect alignRect(x_offset_text, y_offset_text, 200, 50);
        painter.setPen(QPen(Qt::gray, 1, Qt::DashLine));
        painter.drawRect(alignRect); // 绘制对齐区域的边框
        painter.setPen(Qt::darkBlue);
        painter.setFont(QFont("Courier New", 10));
        // 在矩形内右对齐+垂直居中
        painter.drawText(alignRect, Qt::AlignVCenter | Qt::AlignRight, "Aligned Text\n(Right & VCenter)");

        y_offset_text += 60;

        //===============================================================
        // --- 保存与恢复绘图状态 ---
        //===============================================================

        int y_offset_state = 400;
        int x_offset_state = 200;

        painter.setPen(QPen(Qt::black, 1));
        painter.drawText(x_offset_state, y_offset_state, "Before save(): Black Pen");

        // 1.2.5、保存状态
        painter.save();

        // 修改状态
        painter.setPen(QPen(Qt::darkCyan, 4, Qt::DotLine));
        painter.drawText(x_offset_state, y_offset_state + 20, "After save(), changed Pen: Dark Cyan Dot Line");

        // 1.2.5、恢复状态
        painter.restore();

        painter.drawText(x_offset_state, y_offset_state + 40, "After restore(): Black Pen is back");

        // 绘制一个形状来确认画笔确实恢复了
        painter.drawRect(x_offset_state, y_offset_state + 50, 50, 30);

        // QPainter 的析构函数会自动调用 end(),所以在 paintEvent 结束时不需要手动调用。
        // 如果您在 paintEvent 之外手动调用了 painter.begin(...),则需要手动调用 painter.end()。
    }

private:
    QImage sampleImage;
    QPixmap samplePixmap;
};

// 主函数
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    DrawingWidget mainWindow;
    mainWindow.show();

    return app.exec();
}

#include "main.moc" // 包含 moc 文件,用于处理 Q_OBJECT 宏生成的代码

1.3、绘图设备:QPaintDevice

QPaintDevice 是 Qt 绘图系统的抽象基类,表示可以被 QPainter 绘制的目标。

派生类包括:

  • QImage:光栅图像,适合像素级操作。

  • QPixmap:优化为屏幕显示,适合 GUI。

  • QPicture:记录绘图命令,可回放。

  • QPrinter:用于打印输出。

  • QOpenGLPaintDevice:支持 OpenGL 渲染。

  • QWidget(间接支持):通过 paintEvent 使用 QPainter 绘制。

示例代码

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QImage>
#include <QPixmap>
#include <QPicture>
#include <QPrinter>
#include <QPushButton>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QMessageBox>
#include <QPrintDialog>

// 自定义窗口类,用于测试 QPaintDevice 的各种派生类
class PaintDeviceWidget : public QWidget {
public:
    PaintDeviceWidget(QWidget *parent = nullptr) : QWidget(parent) {
        // 设置窗口大小
        setFixedSize(400, 500);

        // 创建按钮用于触发保存和打印
        QPushButton *saveImageButton = new QPushButton("Save as Image", this);
        QPushButton *savePixmapButton = new QPushButton("Save as Pixmap", this);
        QPushButton *savePictureButton = new QPushButton("Save as Picture", this);
        QPushButton *printButton = new QPushButton("Print", this);

        // 布局
        QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(saveImageButton);
        layout->addWidget(savePixmapButton);
        layout->addWidget(savePictureButton);
        layout->addWidget(printButton);
        layout->addStretch();
        setLayout(layout);

        // 连接按钮信号,保存时注意填写后缀
        connect(saveImageButton, &QPushButton::clicked, this, &PaintDeviceWidget::saveToImage);
        connect(savePixmapButton, &QPushButton::clicked, this, &PaintDeviceWidget::saveToPixmap);
        connect(savePictureButton, &QPushButton::clicked, this, &PaintDeviceWidget::saveToPicture);
        connect(printButton, &QPushButton::clicked, this, &PaintDeviceWidget::print);
    }

protected:
    // 重写 paintEvent,在 QWidget 上绘制
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        drawCommonGraphics(&painter, "Drawing on QWidget");
    }

private:
    // 通用的绘制函数,适用于所有 QPaintDevice
    void drawCommonGraphics(QPainter *painter, const QString &title) {
        // 设置画笔和画刷
        painter->setPen(QPen(Qt::blue, 2));
        painter->setBrush(QBrush(Qt::yellow));

        // 绘制矩形
        painter->drawRect(50, 50, 100, 80);

        // 绘制椭圆
        painter->setPen(QPen(Qt::red, 3));
        painter->setBrush(QBrush(Qt::green));
        painter->drawEllipse(50, 150, 100, 80);

        // 绘制文本
        painter->setFont(QFont("Arial", 12));
        painter->setPen(Qt::black);
        painter->drawText(50, 250, title);
    }

    // 在 QImage 上绘制并保存,保存时注意填写后缀
    void saveToImage() {
        QImage image(200, 300, QImage::Format_ARGB32);
        image.fill(Qt::white); // 设置背景色

        QPainter painter(&image);
        painter.setRenderHint(QPainter::Antialiasing);
        drawCommonGraphics(&painter, "Drawing on QImage");

        QString fileName = QFileDialog::getSaveFileName(this, "Save Image", "", "PNG Files (*.png)");
        if (!fileName.isEmpty()) {
            if (image.save(fileName)) {
                QMessageBox::information(this, "Success", "Image saved successfully!");
            } else {
                QMessageBox::warning(this, "Error", "Failed to save image!");
            }
        }
    }

    // 在 QPixmap 上绘制并保存,保存时注意填写后缀
    void saveToPixmap() {
        QPixmap pixmap(200, 300);
        pixmap.fill(Qt::white); // 设置背景色

        QPainter painter(&pixmap);
        painter.setRenderHint(QPainter::Antialiasing);
        drawCommonGraphics(&painter, "Drawing on QPixmap");

        QString fileName = QFileDialog::getSaveFileName(this, "Save Pixmap", "", "PNG Files (*.png)");
        if (!fileName.isEmpty()) {
            if (pixmap.save(fileName)) {
                QMessageBox::information(this, "Success", "Pixmap saved successfully!");
            } else {
                QMessageBox::warning(this, "Error", "Failed to save pixmap!");
            }
        }
    }

    // 在 QPicture 上绘制并保存,保存时注意填写后缀
    void saveToPicture() {
        QPicture picture;
        QPainter painter(&picture);
        painter.setRenderHint(QPainter::Antialiasing);
        drawCommonGraphics(&painter, "Drawing on QPicture");
        painter.end(); // QPicture 需要显式结束

        QString fileName = QFileDialog::getSaveFileName(this, "Save Picture", "", "Picture Files (*.pic)");
        if (!fileName.isEmpty()) {
            if (picture.save(fileName)) {
                QMessageBox::information(this, "Success", "Picture saved successfully!");
            } else {
                QMessageBox::warning(this, "Error", "Failed to save picture!");
            }
        }
    }

    // 在 QPrinter 上绘制并打印
    void print() {
        QPrinter printer;
        QPrintDialog dialog(&printer, this);
        if (dialog.exec() == QDialog::Accepted) {
            QPainter painter(&printer);
            painter.setRenderHint(QPainter::Antialiasing);
            drawCommonGraphics(&painter, "Drawing on QPrinter");
        }
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    PaintDeviceWidget widget;
    widget.show();

    return app.exec();
}

2、样式与填充

2.1、线条样式:QPen

QPen 是 Qt 中用于绘制线条样式的类,适用于路径、形状的轮廓等。它可以配置颜色、宽度、风格、线帽和连接方式。

  • 创建与配置 QPen:可以通过构造函数或 setter 方法配置。

  • 设置线条颜色setColor():颜色可以通过 QColor 或预定义的 Qt::GlobalColor 设置。

  • 设置线条宽度setWidth():宽度以像素为单位,整数或浮点数。宽度为 0 表示“化妆笔”,宽度不随缩放变化。

  • 设置线条风格setStyle(),通过 Qt::PenStyle 枚举设置:

    • Qt::SolidLine:实线

    • Qt::DashLine:虚线

    • Qt::DotLine:点线

    • Qt::DashDotLine:点划线

    • Qt::DashDotDotLine:点划点线

    • Qt::CustomDashLine:自定义虚线

  • 设置线帽风格setCapStyle(),线帽风格定义线条端点的形状,通过 Qt::PenCapStyle 枚举设置:,通过 Qt::PenCapStyle 枚举设置:

    • Qt::SquareCap:方形端点(延伸半个线宽)

    • Qt::RoundCap:圆形端点

    • Qt::FlatCap:平端点(不延伸)

  • 设置连接风格setJionStyle(),连接风格定义多段线连接处的形状,通过 Qt::PenJoinStyle 枚举设置:

    • Qt::MiterJoin:尖角连接

    • Qt::RoundJoin:圆角连接

    • Qt::BevelJoin:斜角连接

  • 使用 QPen 绘制路径和形状:与 QPainter 结合使用,设置后用于绘制线条或形状的轮廓。

  • 示例代码

    #include <QApplication>
    #include <QWidget>
    #include <QPainter>
    #include <QPen>
    #include <QColor>
    #include <QRect>
    #include <QPaintEvent>
    
    // 定义一个自定义的QWidget类,用于演示QPen的使用
    class QPenExampleWidget : public QWidget
    {
        Q_OBJECT // 需要Q_OBJECT宏来支持信号和槽,虽然这个例子没有使用信号槽
    
    public:
        QPenExampleWidget(QWidget *parent = nullptr) : QWidget(parent)
        {
            setWindowTitle("QPen 示例"); // 设置窗口标题
            setMinimumSize(400, 350); // 设置窗口最小大小
        }
    
    protected:
        // 重写paintEvent函数,在这里进行绘图操作
        void paintEvent(QPaintEvent *event) override
        {
            Q_UNUSED(event); // 标记事件参数未使用,避免编译器警告
    
            QPainter painter(this); // 创建一个QPainter对象,用于在当前widget上绘图
            painter.setRenderHint(QPainter::Antialiasing); // 开启抗锯齿,使线条更平滑
    
            int startX = 10;
            int startY = 20;
            int lineLength = 90;
            int shapeWidth = 90;
            int shapeHeight = 30;
            int spacing = 50;
    
            // 1. 默认画笔 (通常是黑色、实线、1像素宽、方头、斜角连接)
            painter.setPen(QPen());
            painter.drawText(startX, startY, "默认画笔:");
            painter.drawLine(startX, startY + 10, startX + lineLength, startY + 10);
    
            // 2. 设置特定颜色和宽度的画笔
            QPen redPen(Qt::red); // 创建红色画笔
            redPen.setWidth(3); // 设置线宽为3像素
            painter.setPen(redPen);
            painter.drawText(startX, startY + spacing, "红色画笔 (宽度 3):");
            painter.drawRect(startX, startY + spacing + 10, shapeWidth, shapeHeight); // 绘制矩形
    
            // 3. 设置浮点数宽度和不同颜色的画笔
            QPen bluePen(QColor(0, 0, 255)); // 使用RGB值创建蓝色画笔
            bluePen.setWidthF(2.5); // 设置线宽为2.5像素(浮点数)
            painter.setPen(bluePen);
            painter.drawText(startX, startY + 2 * spacing, "蓝色画笔 (宽度 2.5 浮点数):");
            painter.drawEllipse(startX, startY + 2 * spacing + 10, shapeWidth, shapeHeight); // 绘制椭圆
    
            // 4. 设置不同线条风格的画笔 (虚线, 点线, 点划线)
            int styleStartX = 150;
            painter.drawText(styleStartX, startY, "不同风格画笔:");
    
            QPen dashPen(Qt::black, 2, Qt::DashLine); // 创建黑色、2像素宽、虚线画笔
            painter.setPen(dashPen);
            painter.drawText(styleStartX, startY + 10, "虚线:");
            painter.drawLine(styleStartX + 50, startY + 10, styleStartX + 50 + lineLength, startY + 10);
    
            QPen dotPen(Qt::black, 2, Qt::DotLine); // 创建黑色、2像素宽、点线画笔
            painter.setPen(dotPen);
            painter.drawText(styleStartX, startY + spacing - 10, "点线:");
            painter.drawLine(styleStartX + 50, startY + spacing - 10, styleStartX + 50 + lineLength, startY + spacing - 10);
    
            QPen dashDotPen(Qt::black, 2, Qt::DashDotLine); // 创建黑色、2像素宽、点划线画笔
            painter.setPen(dashDotPen);
            painter.drawText(styleStartX, startY + 2 * spacing - 20, "点划线:");
            painter.drawLine(styleStartX + 50, startY + 2 * spacing - 20, styleStartX + 50 + lineLength, startY + 2 * spacing - 20);
    
            // 5. 设置不同线帽风格 (Cap Style)
            int capStartX = 10;
            int capStartY = startY + 3 * spacing;
            int capLineLength = 90;
            int capSpacing = 25;
            int capPenWidth = 8;
    
            painter.drawText(capStartX, capStartY, "线帽风格 (宽度为8以示区别):");
    
            QPen squareCapPen(Qt::darkMagenta, capPenWidth, Qt::SolidLine, Qt::SquareCap); // 方形线帽
            painter.setPen(squareCapPen);
            painter.drawText(capStartX, capStartY + 10, "SquareCap (方形帽):");
            painter.drawLine(capStartX, capStartY + 20, capStartX + capLineLength, capStartY + 20);
    
            QPen roundCapPen(Qt::darkMagenta, capPenWidth, Qt::SolidLine, Qt::RoundCap); // 圆形线帽
            painter.setPen(roundCapPen);
            painter.drawText(capStartX, capStartY + 10 + capSpacing, "RoundCap (圆形帽):");
            painter.drawLine(capStartX, capStartY + 20 + capSpacing, capStartX + capLineLength, capStartY + 20 + capSpacing);
    
            QPen flatCapPen(Qt::darkMagenta, capPenWidth, Qt::SolidLine, Qt::FlatCap); // 平坦线帽
            painter.setPen(flatCapPen);
            painter.drawText(capStartX, capStartY + 10 + 2*capSpacing, "FlatCap (平坦帽):");
            painter.drawLine(capStartX, capStartY + 20 + 2*capSpacing, capStartX + capLineLength, capStartY + 20 + 2*capSpacing);
    
    
            // 6. 设置不同连接风格 (Join Style) - 需要绘制连接的多段线才能看出来
            int joinStartX = 150;
            int joinStartY = startY + 3 * spacing;
            int joinPenWidth = 5; // 使用较粗的线条更明显
            int joinSpacing = 60;
    
            painter.drawText(joinStartX, joinStartY, "连接风格 (使用折线展示):");
    
            // 定义一个V字形的多段线点
            QPoint pointsMiter[] = {QPoint(joinStartX, joinStartY + 30), QPoint(joinStartX + 20, joinStartY + 10), QPoint(joinStartX + 40, joinStartY + 30)};
            QPen miterJoinPen(Qt::darkCyan, joinPenWidth, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); // 斜角连接
            painter.setPen(miterJoinPen);
            painter.drawText(joinStartX, joinStartY + 40, "MiterJoin (斜角连接):");
            painter.drawPolyline(pointsMiter, 3);
    
    
            QPoint pointsRound[] = {QPoint(joinStartX + joinSpacing, joinStartY + 30), QPoint(joinStartX + joinSpacing + 20, joinStartY + 10), QPoint(joinStartX + joinSpacing + 40, joinStartY + 30)};
            QPen roundJoinPen(Qt::darkCyan, joinPenWidth, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin); // 圆角连接
            painter.setPen(roundJoinPen);
            painter.drawText(joinStartX + joinSpacing, joinStartY + 40, "RoundJoin (圆角连接):");
            painter.drawPolyline(pointsRound, 3);
    
            QPoint pointsBevel[] = {QPoint(joinStartX + 2*joinSpacing, joinStartY + 30), QPoint(joinStartX + 2*joinSpacing + 20, joinStartY + 10), QPoint(joinStartX + 2*joinSpacing + 40, joinStartY + 30)};
            QPen bevelJoinPen(Qt::darkCyan, joinPenWidth, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin); // 斜面连接
            painter.setPen(bevelJoinPen);
            painter.drawText(joinStartX + 2*joinSpacing, joinStartY + 40, "BevelJoin (斜面连接):");
            painter.drawPolyline(pointsBevel, 3);
    
    
            // 7. 综合应用各种风格的画笔
            QPen customPen(Qt::darkGreen, 4, Qt::DashDotDotLine, Qt::RoundCap, Qt::BevelJoin); // 创建一个自定义画笔
            painter.setPen(customPen);
            painter.drawText(startX, startY + 6 * spacing, "综合画笔示例:");
            painter.drawRect(startX, startY + 6 * spacing + 10, shapeWidth * 2, shapeHeight);
        }
    };
    
    // main函数,程序的入口
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv); // 创建QApplication对象
    
        QPenExampleWidget w; // 创建自定义的窗口widget
        w.show(); // 显示窗口
    
        return a.exec(); // 启动应用程序事件循环
    }
    
    // 需要moc处理,否则无法编译,因为使用了Q_OBJECT宏
    #include "main.moc"
    

2.2、填充样式:QBrush

QBrush 用于定义填充样式,适用于闭合形状(如矩形、椭圆)或路径的内部填充。它支持纯色、渐变、图案和纹理。

  • 创建与配置 QBrush:可以通过构造函数或 setter 方法配置。

  • 设置填充颜色setColor():填充颜色可以通过 QColor 或 Qt::GlobalColor 设置。

  • 设置填充风格setStyle():通过 Qt::BrushStyle 枚举设置:

    • Qt::NoBrush:无填充

    • Qt::SolidPattern:纯色填充

    • Qt::Dense1Pattern ~ Qt::Dense7Pattern:不同密度的点图案

    • Qt::HorPattern:水平线图案

    • Qt::VerPattern:垂直线图案

    • Qt::CrossPattern:交叉线图案

    • Qt::BDiagPattern:反斜线图案

    • Qt::FDiagPattern:正斜线图案

    • Qt::DiagCrossPattern:斜交叉图案

    • Qt::LinearGradientPattern:线性渐变

    • Qt::RadialGradientPattern:径向渐变

    • Qt::ConicalGradientPattern:圆锥渐变

    • Qt::TexturePattern:纹理填充

  • 使用 QBrush 填充路径和形状:与 QPainter 结合,用于填充形状或路径。

  • 示例代码

    #include <QApplication>
    #include <QWidget>
    #include <QPainter>
    #include <QBrush>
    #include <QColor>
    #include <QRect>
    #include <QPaintEvent>
    
    
    class QBrushExampleWidget : public QWidget
    {
        Q_OBJECT // 需要Q_OBJECT宏来支持信号和槽等元对象特性
    
    public:
        QBrushExampleWidget(QWidget *parent = nullptr) : QWidget(parent)
        {
            setWindowTitle("QBrush 示例 (整合)");
            setMinimumSize(500, 400);
        }
    
    protected:
        // 重写paintEvent函数,在这里进行绘图操作
        void paintEvent(QPaintEvent *event) override
        {
            Q_UNUSED(event); // 标记事件参数未使用,避免编译器警告
    
            QPainter painter(this); // 创建一个QPainter对象,用于在当前widget上绘图
            painter.setRenderHint(QPainter::Antialiasing); // 开启抗锯齿,使形状边缘更平滑
    
            // 这里使用一个细的黑色边框,这样填充区域和背景有清晰界限
            QPen thinBlackPen(Qt::black, 1);
            painter.setPen(thinBlackPen);
    
            int startX = 10;
            int startY = 20;
            int shapeSize = 60;
            int spacing = 80;
            int rowSpacing = 120;
    
            // 1. 默认画刷 (通常是 Qt::NoBrush,即无填充)
            painter.drawText(startX, startY, "默认画刷 (无填充):");
            painter.setBrush(QBrush()); // 设置默认画刷 (或使用 QBrush(Qt::NoBrush) )
            painter.drawRect(startX, startY + 10, shapeSize, shapeSize);
    
    
            // 2. 纯色填充 (Qt::SolidPattern)
            QBrush solidBrush(Qt::green, Qt::SolidPattern); // 创建一个绿色纯色画刷
            painter.drawText(startX + shapeSize + spacing, startY, "纯色填充 (绿色):");
            painter.setBrush(solidBrush); // 设置当前画刷
            painter.drawRect(startX + shapeSize + spacing, startY + 10, shapeSize, shapeSize); // 绘制填充矩形
    
            QBrush yellowBrush(QColor(255, 255, 0)); // 使用RGB值创建一个黄色纯色画刷
            painter.drawText(startX + 2 * (shapeSize + spacing), startY, "纯色填充 (黄色):");
            painter.setBrush(yellowBrush);
            painter.drawEllipse(startX + 2 * (shapeSize + spacing), startY + 10, shapeSize, shapeSize); // 绘制填充椭圆
    
    
            // 3. 不同密度的点图案 (Dense Patterns)
            int patternY = startY + rowSpacing;
            painter.drawText(startX, patternY, "点图案填充:");
    
            QBrush dense1Brush(Qt::blue, Qt::Dense1Pattern); // 蓝色密集点图案
            painter.setBrush(dense1Brush);
            painter.drawText(startX, patternY + 10, "Dense1Pattern (最密集):");
            painter.drawRect(startX, patternY + 20, shapeSize, shapeSize);
    
            QBrush dense3Brush(Qt::red, Qt::Dense3Pattern); // 红色中等密度点图案
            painter.setBrush(dense3Brush);
            painter.drawText(startX + shapeSize + spacing, patternY + 10, "Dense3Pattern (中等密度):");
            painter.drawRect(startX + shapeSize + spacing, patternY + 20, shapeSize, shapeSize);
    
            QBrush dense7Brush(Qt::gray, Qt::Dense7Pattern); // 灰色稀疏点图案
            painter.setBrush(dense7Brush);
            painter.drawText(startX + 2 * (shapeSize + spacing), patternY + 10, "Dense7Pattern (最稀疏):");
            painter.drawRect(startX + 2 * (shapeSize + spacing), patternY + 20, shapeSize, shapeSize);
    
    
            // 4. 不同线图案 (Line Patterns)
            int linePatternY = startY + 2 * rowSpacing;
            painter.drawText(startX, linePatternY, "线图案填充:");
    
            QBrush horBrush(Qt::darkGreen, Qt::HorPattern); // 水平线图案画刷
            painter.setBrush(horBrush);
            painter.drawText(startX, linePatternY + 10, "HorPattern (水平线):");
            painter.drawRect(startX, linePatternY + 20, shapeSize, shapeSize);
    
            QBrush verBrush(Qt::darkBlue, Qt::VerPattern); // 垂直线图案画刷
            painter.setBrush(verBrush);
            painter.drawText(startX + shapeSize + spacing, linePatternY + 10, "VerPattern (垂直线):");
            painter.drawRect(startX + shapeSize + spacing, linePatternY + 20, shapeSize, shapeSize);
    
            QBrush crossBrush(Qt::darkRed, Qt::CrossPattern); // 交叉线图案画刷
            painter.setBrush(crossBrush);
            painter.drawText(startX + 2 * (shapeSize + spacing), linePatternY + 10, "CrossPattern (交叉线):");
            painter.drawRect(startX + 2 * (shapeSize + spacing), linePatternY + 20, shapeSize, shapeSize);
    
    
            // 5. 斜线图案 (Diagonal Patterns)
            int diagPatternY = startY + 3 * rowSpacing;
            painter.drawText(startX, diagPatternY, "斜线图案填充:");
    
            QBrush bDiagBrush(Qt::magenta, Qt::BDiagPattern); // 反斜线图案画刷 (从左下到右上)
            painter.setBrush(bDiagBrush);
            painter.drawText(startX, diagPatternY + 10, "BDiagPattern (反斜线):");
            painter.drawRect(startX, diagPatternY + 20, shapeSize, shapeSize);
    
            QBrush fDiagBrush(Qt::cyan, Qt::FDiagPattern); // 正斜线图案画刷 (从左上到右下)
            painter.setBrush(fDiagBrush);
            painter.drawText(startX + shapeSize + spacing, diagPatternY + 10, "FDiagPattern (正斜线):");
            painter.drawRect(startX + shapeSize + spacing, diagPatternY + 20, shapeSize, shapeSize);
    
            QBrush diagCrossBrush(Qt::darkYellow, Qt::DiagCrossPattern); // 斜交叉图案画刷
            painter.setBrush(diagCrossBrush);
            painter.drawText(startX + 2 * (shapeSize + spacing), diagPatternY + 10, "DiagCrossPattern (斜交叉):");
            painter.drawRect(startX + 2 * (shapeSize + spacing), diagPatternY + 20, shapeSize, shapeSize);
    
    
            // 注意:渐变 (LinearGradientPattern, RadialGradientPattern, ConicalGradientPattern)
            
            // 关于纹理填充 (TexturePattern)
            // 纹理填充需要一个QPixmap或QImage作为纹理源,
            // 这里为了保持代码简洁不直接包含图片文件,如果需要可以自行加载图片创建QBrush。
            // QBrush textureBrush(QPixmap(":/path/to/your/texture.png")); // 示例:加载图片创建纹理画刷
            // painter.setBrush(textureBrush);
            // painter.drawRect(...);
        }
    };
    
    // main函数,程序的入口
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv); 
    
        QBrushExampleWidget w; 
        w.show(); // 显示窗口
    
        return a.exec(); 
    }
    
    // 需要moc处理,否则无法编译,因为自定义类中使用了Q_OBJECT宏
    #include "main.moc"
    

2.3、渐变填充:QGradient

QGradient 是 QBrush 的高级填充方式,提供线性、径向和圆锥渐变效果。一般使用其子类:QLinearGradient、QRadialGradient 和 QConicalGradient。通过 QBrush实现效果。

注意:当渐变定义区域小于实际绘制区域是,应设置扩展方式获得预期的渐变效果。

2.3.1、QGradient 基类

QGradient 提供通用的渐变设置方法:

  • setColorAt(qreal pos, const QColor &color):设置颜色停止点

  • setSpread(QGradient::Spread spread):设置渐变扩展方式:

    • QGradient::PadSpread:填充边界外的区域

    • QGradient::ReflectSpread:反射渐变

    • QGradient::RepeatSpread:重复渐变

2.3.2、QLinearGradient:线性渐变:线性渐变沿直线从起点到终点过渡颜色。

2.3.2.1、构造函数

  • QLinearGradient():默认构造,未初始化起点和终点。

  • QLinearGradient(qreal x1, qreal y1, qreal x2, qreal y2):指定起点 (x1, y1) 和终点 (x2, y2)。

  • QLinearGradient(const QPointF &start, const QPointF &finalStop):使用 QPointF 指定起点和终点。

2.3.2.2、几何设置函数:设置或获取线性渐变的起点和终点。

  • void setStart(qreal x, qreal y) :设置渐变的起点坐标。

  • QPointF start() const:返回渐变的起点坐标。

  • void setFinalStop(qreal x, qreal y):设置渐变的终点坐标。

  • QPointF finalStop() const:返回渐变的终点坐标。

2.3.3、QRadialGradient:径向渐变:径向渐变从中心点向外扩展,基于半径和可选的焦点。

2.3.3.1、构造函数

  • QRadialGradient():默认构造,未初始化中心、半径或焦点。

  • QRadialGradient(qreal cx, qreal cy, qreal radius):指定中心 (cx, cy) 和半径,焦点默认与中心重合。

  • QRadialGradient(qreal cx, qreal cy, qreal radius, qreal fx, qreal fy):指定中心、半径和焦点 (fx, fy)。

  • QRadialGradient(const QPointF ¢er, qreal radius, const QPointF &focalPoint):使用 QPointF。

2.3.3.2、几何设置函数:设置或获取径向渐变的中心、半径和焦点

  • void setCenter(qreal x, qreal y) :设置渐变的中心点坐标。

  • void setFocalPoint(qreal x, qreal y):设置渐变的焦点坐标(颜色渐变的起点)。

  • void setRadius(qreal radius):设置渐变的半径。

2.3.4、QConicalGradient:圆锥渐变:圆锥渐变围绕中心点按角度旋转颜色。

2.3.4.1、构造函数

  • QConicalGradient():默认构造,未初始化中心或角度。

  • QConicalGradient(qreal cx, qreal cy, qreal angle):指定中心 (cx, cy) 和起始角度。

  • QConicalGradient(const QPointF ¢er, qreal angle):使用 QPointF。

2.3.4.2、几何设置函数:这些函数用于设置或获取圆锥渐变的中心和起始角度。

  • void setCenter(qreal x, qreal y) :设置渐变的中心点坐标。

  • void setAngle(qreal angle):设置渐变的起始角度。

2.3.5、示例代码:注意渐变区域与实际绘制区域大小

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QBrush>
#include <QColor>
#include <QRect>
#include <QPaintEvent>
#include <QLinearGradient> // 包含线性渐变的头文件
#include <QRadialGradient> // 包含径向渐变的头文件
#include <QConicalGradient> // 包含圆锥渐变的头文件


class GradientWidget : public QWidget
{
    Q_OBJECT

public:
    GradientWidget(QWidget *parent = nullptr) : QWidget(parent)
    {
        setWindowTitle("QGradient 示例 (整合)");
        setMinimumSize(600, 650);
    }

protected:
    // 重写paintEvent函数,在这里进行绘图操作
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event); // 标记事件参数未使用,避免编译器警告

        QPainter painter(this); // 创建一个QPainter对象,用于在当前widget上绘图
        painter.setRenderHint(QPainter::Antialiasing); // 开启抗锯齿,使形状边缘更平滑

        // 设置一个细的黑色边框,这样填充区域和背景有清晰界限
        QPen thinBlackPen(Qt::black, 1);
        painter.setPen(thinBlackPen);

        int startX = 10;
        int startY = 20;
        int shapeWidth = 150;
        int shapeHeight = 80;
        int spacing = 20;
        int rowSpacing = 120;



        painter.drawText(startX, startY, "渐变填充示例:");

        // 1. 线性渐变 (QLinearGradient)
        int linearY = startY + spacing;
        // 定义线性渐变的起始点和结束点
        QLinearGradient linearGradient(startX, linearY + 10, startX + shapeWidth, linearY + 10 + shapeHeight);
        // 添加颜色停止点:位置 (0.0 到 1.0) 和颜色
        linearGradient.setColorAt(0.0, Qt::red);      // 起始点 (0.0) 颜色为红色
        linearGradient.setColorAt(0.5, Qt::yellow); // 中间点 (0.5) 颜色为黄色
        linearGradient.setColorAt(1.0, Qt::blue);     // 结束点 (1.0) 颜色为蓝色

        QBrush linearBrush(linearGradient); // 使用线性渐变创建画刷
        painter.setBrush(linearBrush); // 设置当前画刷
        painter.drawText(startX, linearY, "QLinearGradient (线性渐变):");
        painter.drawRect(startX, linearY + 10, shapeWidth, shapeHeight); // 绘制一个矩形来展示渐变


        // 2. 径向渐变 (QRadialGradient)
        int radialY = startY + rowSpacing;
        // 定义径向渐变的中心点、半径和焦点 (焦点是颜色开始扩散的点,通常与中心点相同)
        // QRadialGradient(centerX, centerY, radius, focalX, focalY)
        QRadialGradient radialGradient(startX + shapeWidth/2, radialY + 10 + shapeHeight/2, shapeWidth/2, // 中心点和半径
                                       startX + shapeWidth/2, radialY + 10 + shapeHeight/2); // 焦点 (此处与中心点重合)
        radialGradient.setColorAt(0.0, Qt::white); // 中心颜色为白色
        radialGradient.setColorAt(0.6, Qt::darkCyan); // 中间颜色为深青色
        radialGradient.setColorAt(1.0, Qt::black); // 边缘颜色为黑色

        QBrush radialBrush(radialGradient); // 使用径向渐变创建画刷
        painter.setBrush(radialBrush);
        painter.drawText(startX, radialY, "QRadialGradient (径向渐变):");
        painter.drawEllipse(startX, radialY + 10, shapeWidth, shapeHeight); // 绘制一个椭圆来展示径向渐变


        // 3. 圆锥渐变 (QConicalGradient)
        int conicalY = startY + 2 * rowSpacing;
        // 定义圆锥渐变的中心点和起始角度 (角度为顺时针,0度在3点钟方向)
        // QConicalGradient(centerX, centerY, startAngle)
        QConicalGradient conicalGradient(startX + shapeWidth/2, conicalY + 10 + shapeHeight/2, 0.0); // 中心点,起始角度0度
        conicalGradient.setColorAt(0.0, Qt::red);     // 0度 (右侧) 颜色为红色
        conicalGradient.setColorAt(0.25, Qt::green); // 90度 (下方) 颜色为绿色
        conicalGradient.setColorAt(0.5, Qt::blue);  // 180度 (左侧) 颜色为蓝色
        conicalGradient.setColorAt(0.75, Qt::yellow); // 270度 (上方) 颜色为黄色
        conicalGradient.setColorAt(1.0, Qt::red);     // 360度颜色回到红色 (与0度连接)

        QBrush conicalBrush(conicalGradient); // 使用圆锥渐变创建画刷
        painter.setBrush(conicalBrush);
        painter.drawText(startX, conicalY, "QConicalGradient (圆锥渐变):");
        painter.drawEllipse(startX, conicalY + 10, shapeWidth, shapeHeight); // 绘制一个椭圆来展示圆锥渐变


        // 4. 渐变扩展模式 (Spread Modes)
        int spreadY = startY + 3 * rowSpacing;
        painter.drawText(startX, spreadY, "渐变扩展模式 (以线性渐变为例):");

        // 定义一个只覆盖一部分区域的线性渐变
        QLinearGradient partialGradient(startX, spreadY + 10, startX + shapeWidth/2, spreadY + 10);
        partialGradient.setColorAt(0.0, Qt::magenta);
        partialGradient.setColorAt(1.0, Qt::cyan);

        // QGradient::PadSpread (默认): 边界外的区域用渐变的结束颜色填充
        partialGradient.setSpread(QGradient::PadSpread);
        QBrush padSpreadBrush(partialGradient);
        painter.setBrush(padSpreadBrush);
        painter.drawText(startX, spreadY + 10, "PadSpread (填充):");
        painter.drawRect(startX, spreadY + 20, shapeWidth, shapeHeight/2);


        // QGradient::RepeatSpread: 渐变图案在边界外重复
        partialGradient.setSpread(QGradient::RepeatSpread);
        QBrush repeatSpreadBrush(partialGradient);
        painter.setBrush(repeatSpreadBrush);
        painter.drawText(startX, spreadY + 10 + shapeHeight/2 + spacing/2, "RepeatSpread (重复):");
        painter.drawRect(startX, spreadY + 20 + shapeHeight/2 + spacing/2, shapeWidth, shapeHeight/2);


        // QGradient::ReflectSpread: 渐变图案在边界外反射(镜像)重复
        int reflectY = startY + 4 * rowSpacing;
        painter.drawText(startX, reflectY, "ReflectSpread (反射):");

        // 重新定义一个不同的部分渐变
        QLinearGradient reflectGradient(startX, reflectY + 10, startX + shapeWidth/2, reflectY + 10);
        reflectGradient.setColorAt(0.0, Qt::darkYellow);
        reflectGradient.setColorAt(1.0, Qt::darkGreen);
        reflectGradient.setSpread(QGradient::ReflectSpread);
        QBrush reflectSpreadBrush(reflectGradient);
        painter.setBrush(reflectSpreadBrush);
        painter.drawRect(startX, reflectY + 20, shapeWidth, shapeHeight);

    }
};


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    GradientWidget w;
    w.show();

    return a.exec();
}

// 需要moc处理,否则无法编译,因为自定义类中使用了Q_OBJECT宏
#include "main.moc"

3、复杂图形与区域

3.1、复杂路径绘制:QPainterPath

QPainterPath 是一个强大的类,用于定义和管理复杂的 2D 路径。它可以表示任意形状的路径,包括直线、曲线、基本形状和文本,并支持描边和填充。

  • 定义复杂的 2D 路径,包含直线、贝塞尔曲线、矩形、椭圆等。

  • 支持路径的布尔运算(联合、相交等),便于构造复杂形状。

  • 可用于描边(stroke)、填充(fill)以及裁剪。

3.1.1、构建路径:支持基本形状、线条、曲线和文本。

3.1.1.1、添加基本形状

  • void addRect(const QRectF &rect):添加矩形路径。

  • void addEllipse(const QRectF &rect):添加椭圆路径(矩形定义外接框)。

  • void addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius):添加圆角矩形。

  • void addPolygon(const QPolygonF &polygon):添加多边形路径。

3.1.1.2、添加线条与曲线

  • void moveTo(qreal x, qreal y) / void moveTo(const QPointF &point):移动当前点到指定位置(不绘制)。

  • void lineTo(qreal x, qreal y) / void lineTo(const QPointF &point):从当前点绘制直线到指定点。

  • void quadTo(qreal cx, qreal cy, qreal endX, qreal endY):绘制二次贝塞尔曲线(一个控制点)。

  • void cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, qreal endX, qreal endY):绘制三次贝塞尔曲线(两个控制点)。

  • void arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength):绘制椭圆弧。

3.1.1.3、添加文本

  • void addText(qreal x, qreal y, const QFont &font, const QString &text):在指定位置添加文本路径。

3.1.1.4、路径闭合

  • void closeSubpath():闭合当前子路径(连接当前点与子路径起点)。

3.1.2、路径操作:联合、相交、差集:用于组合多个路径

  • QPainterPath united(const QPainterPath &other):返回两个路径的联合。

  • QPainterPath intersected(const QPainterPath &other):返回两个路径的交集。

  • QPainterPath subtracted(const QPainterPath &other):返回当前路径减去另一路径的差集。

  • QPainterPath simplified():简化路径,移除冗余点。

  • operator|, operator&, operator-:分别对应联合、相交、差集的快捷操作。

3.1.3、使用 QPainterPath 进行绘制:结合 QPen 和 QBrush 实现描边和填充

QPainterPath 与 QPainter 结合,通过 drawPath 绘制路径。

  • QPainter::drawPath(const QPainterPath &path):绘制路径。

  • QPainter::setPen(QPen):设置描边样式。

  • QPainter::setBrush(QBrush):设置填充样式。

3.1.4、路径碰撞检测

  • bool contains(const QPointF &point) const:判断点是否在路径内(填充区域)。

  • bool contains(const QRectF &rect) const:判断矩形是否完全在路径内。

  • bool intersects(const QRectF &rect) const:判断矩形是否与路径相交。

3.1.5、示例代码

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QPainterPath> // 包含QPainterPath头文件
#include <QPen>
#include <QBrush>
#include <QColor>
#include <QRectF>
#include <QPointF>
#include <QFont>
#include <QPaintEvent>
#include <QPolygonF> // 包含QPolygonF头文件


class PathWidget : public QWidget
{
    Q_OBJECT // 需要Q_OBJECT宏来支持信号和槽等元对象特性

public:
    PathWidget(QWidget *parent = nullptr) : QWidget(parent)
    {
        setWindowTitle("QPainterPath 示例 (整合)");
        setMinimumSize(800, 700);
    }

protected:
    // 重写paintEvent函数,在这里进行绘图操作
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event); // 标记事件参数未使用,避免编译器警告

        QPainter painter(this); // 创建一个QPainter对象,用于在当前widget上绘图
        painter.setRenderHint(QPainter::Antialiasing); // 开启抗锯齿,使路径边缘更平滑

        // 设置默认的描边和填充画笔
        painter.setPen(QPen(Qt::black, 2)); // 黑色,2像素宽描边
        painter.setBrush(QBrush(Qt::cyan, Qt::SolidPattern)); // 青色纯色填充

        int startX = 10;
        int startY = 20;
        int spacingY = 150;
        int spacingX = 200;
        //=======================================
        // --- 1. 构建路径示例 ---
        //=======================================

        // 1.1 添加基本形状
        painter.drawText(startX, startY, "1.1 添加基本形状:");
        QPainterPath shapesPath;
        shapesPath.addRect(QRectF(startX, startY + 10, 100, 50)); // 添加矩形
        shapesPath.addEllipse(QRectF(startX + 120, startY + 10, 50, 50)); // 添加椭圆
        shapesPath.addRoundedRect(QRectF(startX + 180, startY + 10, 100, 50), 10, 10); // 添加圆角矩形

        QPolygonF polygon; // 创建一个多边形
        polygon << QPointF(startX + 300, startY + 60) << QPointF(startX + 350, startY + 10) << QPointF(startX + 400, startY + 60) << QPointF(startX + 350, startY + 100);
        shapesPath.addPolygon(polygon); // 添加多边形

        painter.setBrush(Qt::lightGray); // 为形状路径设置不同的填充颜色
        painter.drawPath(shapesPath); // 绘制包含基本形状的路径
        painter.setBrush(Qt::cyan); // 恢复默认填充

        // 1.2 添加线条与曲线
        int linesY = startY + spacingY;
        painter.drawText(startX, linesY, "1.2 添加线条与曲线:");
        QPainterPath linesPath;
        linesPath.moveTo(startX, linesY + 10); // 移动到起点 (不绘制)
        linesPath.lineTo(startX + 50, linesY + 60); // 绘制直线到 (50, 60)
        linesPath.quadTo(startX + 100, linesY + 10, startX + 150, linesY + 60); // 绘制二次贝塞尔曲线 (控制点 100, 10)
        linesPath.cubicTo(startX + 200, linesY + 10, startX + 250, linesY + 110, startX + 300, linesY + 60); // 绘制三次贝塞尔曲线 (控制点 200, 10 和 250, 110)
        linesPath.arcTo(QRectF(startX + 320, linesY + 10, 50, 50), 0, 90); // 添加一个 90 度的圆弧 (从 0 度到 90 度)

        // 闭合一个子路径示例 (三角形)
        linesPath.moveTo(startX + 400, linesY + 10);
        linesPath.lineTo(startX + 450, linesY + 60);
        linesPath.lineTo(startX + 400, linesY + 60);
        linesPath.closeSubpath(); // 闭合当前子路径,形成三角形

        painter.setBrush(Qt::NoBrush); // 只描边,不填充
        painter.drawPath(linesPath); // 绘制包含线条和曲线的路径
        painter.setBrush(Qt::cyan); // 恢复默认填充


        // 1.3 添加文本
        int textY = startY + 2 * spacingY;
        painter.drawText(startX, textY, "1.3 添加文本:");
        QPainterPath textPath;
        QFont font("Arial", 30, QFont::Bold); // 创建一个粗体 Arial 字体,大小为 30
        textPath.addText(startX, textY + 40, font, "Hello Qt Path!"); // 将文本转换为路径

        painter.setBrush(Qt::darkBlue); // 用深蓝色填充文本路径
        painter.drawPath(textPath); // 绘制文本路径
        painter.setBrush(Qt::cyan); // 恢复默认填充

        //==========================================
        // --- 2. 路径操作示例 ---
        //==========================================

        int opsY = startY + 3 * spacingY;
        painter.drawText(startX, opsY, "2. 路径操作 (联合、相交、差集):");

        // 创建两个用于操作的原始路径
        QPainterPath pathA, pathB;
        pathA.addEllipse(QRectF(startX, opsY + 20, 100, 100)); // 圆形 A
        pathB.addRect(QRectF(startX + 50, opsY + 70, 100, 100)); // 矩形 B

        // 2.1 联合 (United)
        QPainterPath unionPath = pathA.united(pathB); // A 和 B 的联合
        painter.drawText(startX, opsY + 140, "A 联合 B:");
        painter.setPen(QPen(Qt::darkGreen, 2)); // 绿色描边
        painter.setBrush(Qt::green); // 绿色填充
        painter.drawPath(unionPath); // 绘制联合路径

        // 2.2 相交 (Intersected)
        QPainterPath intersectPath = pathA.intersected(pathB); // A 和 B 的交集
        painter.drawText(startX + spacingX, opsY + 140, "A 相交 B:");
        painter.translate(spacingX, 0); // 临时平移绘图坐标系
        painter.setPen(QPen(Qt::darkRed, 2)); // 红色描边
        painter.setBrush(Qt::red); // 红色填充
        painter.drawPath(intersectPath); // 绘制相交路径
        painter.translate(-spacingX, 0); // 恢复绘图坐标系

        // 2.3 差集 (Subtracted)
        QPainterPath subtractPath = pathA.subtracted(pathB); // A 减去 B 的差集
        painter.drawText(startX + 2 * spacingX, opsY + 140, "A 减去 B:");
        painter.translate(2 * spacingX, 0); // 临时平移
        painter.setPen(QPen(Qt::darkBlue, 2)); // 蓝色描边
        painter.setBrush(Qt::blue); // 蓝色填充
        painter.drawPath(subtractPath); // 绘制差集路径
        painter.translate(-2 * spacingX, 0); // 恢复

        // 绘制原始路径以便对比 (可选)
        painter.setPen(QPen(Qt::gray, 1, Qt::DashLine)); // 灰色虚线
        painter.setBrush(Qt::NoBrush); // 无填充
        painter.drawPath(pathA);
        painter.drawPath(pathB);


        // --- 3. 路径碰撞检测 (注意:在 paintEvent 中直观演示碰撞检测结果较复杂,这里仅通过文本说明概念) ---
        // bool contains(const QPointF &point) const;
        // bool contains(const QRectF &rect) const;
        // bool intersects(const QRectF &rect) const;
        // 例如:
        // QPainterPath detectionPath;
        // detectionPath.addEllipse(QRectF(500, 500, 100, 100));
        // QPointF testPoint(550, 550);
        // bool isInside = detectionPath.contains(testPoint); // 判断点是否在路径内

        // 在 paintEvent 中,你通常会根据这些检测结果来改变绘制行为或状态,而不是直接绘制布尔值。
        // 由于空间和复杂性考虑,这里不进行绘制演示,仅通过上述代码片段说明用法。
    }
};


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    PathWidget w;
    w.show(); // 显示窗口

    return a.exec();
}

// 需要moc处理,否则无法编译,因为自定义类中使用了Q_OBJECT宏
#include "main.moc"

3.2、2D 区域:QRegion

QRegion 表示 2D 平面上的区域,是一个由像素组成的区域,通常由矩形、多边形或其他形状组成,常用于裁剪、碰撞检测和窗口形状定义。

3.2.1、创建 QRegion:可以从矩形、多边形、位图等创建。

  • QRegion():创建空区域。

  • QRegion(const QRect &rect):从矩形创建区域。

  • QRegion(const QPolygon &polygon):从多边形创建区域。

  • QRegion(const QBitmap &bitmap):从位图创建区域(非零像素表示区域)。

  • QRegion(int x, int y, int w, int h):从指定坐标和尺寸创建矩形区域。

  • QRegion translated(int dx, int dy) const:返回平移后的区域。

  • static QRegion fromBitmap(const QBitmap &bitmap):从位图创建(静态方法)。

3.2.2、区域操作:联合、相交、差集、异或:用于组合多个区域

  • QRegion united(const QRegion &other) const:联合(并集)。

  • QRegion intersected(const QRegion &other) const:相交(交集)。

  • QRegion subtracted(const QRegion &other) const:差集(当前区域减去另一区域)。

  • QRegion xored(const QRegion &other) const:异或(非重叠部分)。

  • operator|, operator&, operator-, operator^:分别对应联合、相交、差集、异或。

3.2.3、使用 QRegion 进行裁剪 :通过 QPainter::setClipRegion 设置裁剪区域

  • void QPainter::setClipRegion(const QRegion &region):设置裁剪区域。

  • QRegion QPainter::clipRegion() const:返回当前裁剪区域。

3.2.4、使用 QRegion 进行碰撞检测

  • bool contains(const QPoint &point) const:判断点是否在区域内。

  • bool contains(const QRect &rect) const:判断矩形是否完全在区域内。

  • bool intersects(const QRegion &region) const:判断区域是否与另一区域相交。

  • bool isEmpty() const:判断区域是否为空。

3.2.5、示例代码

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QRegion>
#include <QPolygon>
#include <QBitmap>
#include <QDebug>

class MyWidget : public QWidget {
protected:
    void paintEvent(QPaintEvent *) override {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing); // 启用抗锯齿
        //=========================
        // 2.2 创建 QRegion
        //=========================
        
        // 2.2.1 构造函数
        // 矩形区域
        QRegion region1(QRect(50, 50, 100, 100));
        // 多边形区域,三角形
        QPolygon polygon({QPoint(150, 50), QPoint(200, 100), QPoint(150, 150)});
        QRegion region2(polygon);
        // 位图区域,圆形
        QBitmap bitmap(50, 50);
        bitmap.fill(Qt::color0); // 透明
        QPainter bitmapPainter(&bitmap);
        bitmapPainter.setBrush(Qt::color1); // 不透明
        bitmapPainter.drawEllipse(0, 0, 50, 50);
        QRegion region3(bitmap);
        region3 = region3.translated(250, 50); // 平移到合适位置

        // 2.2.2 其他创建方法
        // 平移区域
        QRegion translatedRegion = region1.translated(20, 20);
        
        

        //=========================================
        // 2.3 区域操作:联合、相交、差集、异或
        //=========================================
        
        QRegion region4(QRect(100, 100, 100, 100));
        QRegion unionRegion = region1.united(region4); // 联合
        QRegion intersectRegion = region1.intersected(region4); // 相交
        QRegion subtractRegion = region1.subtracted(region4); // 差集
        QRegion xorRegion = region1.xored(region4); // 异或

        //================================
        // 2.4 使用 QRegion 进行裁剪
        //================================
        
        // 绘制裁剪效果:仅在 region1 内填充蓝色
        painter.setClipRegion(region1);
        painter.fillRect(0, 0, 200, 200, Qt::blue); // 仅 (50,50,100,100) 被填充
        painter.setClipping(false); // 关闭裁剪以继续其他绘制

        // 绘制原始区域
        painter.setPen(QPen(Qt::black, 1));
        painter.setBrush(QBrush(Qt::yellow, Qt::DiagCrossPattern));
        painter.drawRects(region1.rects()); // 绘制 region1
        painter.setBrush(QBrush(Qt::green, Qt::CrossPattern));
        painter.drawPolygon(polygon); // 绘制 region2
        painter.setBrush(QBrush(Qt::red, Qt::Dense4Pattern));
        painter.drawEllipse(250, 50, 50, 50); // 绘制 region3
        painter.setBrush(QBrush(Qt::cyan, Qt::HorPattern));
        painter.drawRects(translatedRegion.rects()); // 绘制 translatedRegion

        // 绘制布尔运算结果
        painter.setPen(QPen(Qt::black, 1));
        painter.setBrush(QBrush(Qt::magenta, Qt::SolidPattern));
        painter.translate(0, 200); // 下移绘制区域
        painter.drawRects(unionRegion.rects()); // 联合
        painter.drawText(10, 150, "Union");
        painter.translate(150, 0);
        painter.drawRects(intersectRegion.rects()); // 相交
        painter.drawText(10, 150, "Intersection");
        painter.translate(150, 0);
        painter.drawRects(subtractRegion.rects()); // 差集
        painter.drawText(10, 150, "Subtraction");
        painter.translate(150, 0);
        painter.drawRects(xorRegion.rects()); // 异或
        painter.drawText(10, 150, "XOR");

        //===============================
        // 2.5 使用 QRegion 进行碰撞检测
        //===============================
        
        bool pointInside = region1.contains(QPoint(100, 100)); // true
        bool rectInside = region1.contains(QRect(60, 60, 20, 20)); // true
        bool regionsIntersect = region1.intersects(region4); // true
        bool isEmpty = region1.isEmpty(); // false

        // 输出碰撞检测结果到控制台
        qDebug() << "Point (100,100) in region1:" << pointInside;
        qDebug() << "Rect (60,60,20,20) in region1:" << rectInside;
        qDebug() << "Region1 intersects region4:" << regionsIntersect;
        qDebug() << "Region1 is empty:" << isEmpty;

        // 在窗口显示碰撞检测结果
        painter.resetTransform(); // 重置变换
        painter.drawText(10, 450, QString("Point in region1: %1").arg(pointInside));
        painter.drawText(10, 470, QString("Rect in region1: %1").arg(rectInside));
        painter.drawText(10, 490, QString("Regions intersect: %1").arg(regionsIntersect));
        painter.drawText(10, 510, QString("Region1 is empty: %1").arg(isEmpty));
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.resize(500, 450);
    widget.show();
    return app.exec();
}

4、变换与坐标系统

4.1、2D 变换:QTransform

QTransform 是 Qt 框架中用于处理 2D 图形变换的核心类,支持平移、缩放、旋转和剪切等操作。它本质上是一个 3x3 矩阵,用于描述 2D 空间中的线性变换和仿射变换。QPainter 提供了 setTransform() 方法将 QTransform 应用于绘制操作。

4.1.1、理解 2D 变换的概念

2D 变换用于改变图形的几何属性,包括位置、大小、方向和形状。

  • 平移(Translation):将图形沿 X 或 Y 轴移动指定距离。

    • 数学表示:(x, y) → (x + dx, y + dy)。

  • 缩放(Scaling):按比例放大或缩小图形。

    • 数学表示:(x, y) → (sx * x, sy * y),其中 sx 和 sy 是缩放因子。

  • 旋转(Rotation):围绕某点(通常是原点)旋转图形。

    • 数学表示:(x, y) → (x * cosθ - y * sinθ, x * sinθ + y * cosθ),θ 为旋转角度。

  • 剪切(Shearing):使图形沿某个轴倾斜,产生形变。

    • 数学表示:(x, y) → (x + shx * y, y + shy * x),shx 和 shy 是剪切因子。

4.1.2、创建与配置 QTransform

  • 默认构造函数:QTransform()

  • 直接指定矩阵元素:QTransform(m11, m12, m13, m21, m22, m23, dx, dy, m33);

    [ m11  m12  dx ]
    [ m21  m22  dy ]
    [ m13  m23  m33 ]
  • 通常 m33 = 1,m13 = m23 = 0,用于仿射变换。

4.1.3、应用变换:translate(), scale(), rotate(), shear()

  • 平移:translate(dx, dy): 向x轴移动 dx像素,向Y轴移动 dy 像素

  • 缩放:scale(sx, sy): X 轴放大sx 倍,Y 轴缩小到sy 倍

  • 旋转:rotate(angle, axis = Qt::ZAxis):角度以度为单位,逆时针为正。

  • 剪切:shear(shx, shy): X 轴剪切因子 shx,Y 轴剪切因子 shy。

  • 组合变换: 变换是累积的,顺序会影响结果,先平移再旋转与先旋转再平移效果不同。

3.1.4、矩阵变换 (Matrix Transformation)

QTransform 内部使用 3x3 矩阵表示仿射变换,矩阵形式为:

[ m11  m12  dx ]
[ m21  m22  dy ]
[  0    0    1 ]
  • 点变换:对点 (x, y) 应用变换,结果为:

    x' = m11 * x + m21 * y + dx
    y' = m12 * x + m22 * y + dy
  • 自定义矩阵:

    QTransform transform;
    transform.setMatrix(1, 0.2, 0, 0.1, 1, 0, 50, 50, 1); // 自定义矩阵
  • 矩阵运算: QTransform 支持矩阵乘法(变换组合):

    QTransform t1, t2;
    t1.translate(100, 0);
    t2.rotate(30);
    QTransform combined = t1 * t2; // 先旋转再平移

3.1.5、示例代码

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QTransform>
#include <QPaintEvent>

class TransformWidget : public QWidget {
public:
    TransformWidget(QWidget *parent = nullptr) : QWidget(parent) {
        setMinimumSize(600, 400); // 设置窗口最小尺寸
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing); // 启用抗锯齿

        // 保存初始状态
        painter.save();

        // 1. 绘制原始矩形(无变换,作为参考)
        painter.setPen(Qt::black);
        painter.setBrush(Qt::NoBrush);
        painter.drawText(20, 20, "Original Rect (No Transform)");
        painter.drawRect(20, 30, 50, 30);

        // 2. 平移变换
        QTransform translateTransform;
        translateTransform.translate(100, 100); // 向右 100 像素,向下 100 像素
        painter.setTransform(translateTransform);
        painter.setPen(Qt::blue);
        painter.drawText(0, -10, "Translated Rect");
        painter.drawRect(0, 0, 50, 30);

        // 恢复状态,避免影响后续绘制
        painter.restore();
        painter.save();

        // 3. 缩放变换
        QTransform scaleTransform;
        scaleTransform.scale(2.0, 0.5); // X 轴放大 2 倍,Y 轴缩小 0.5 倍
        painter.setTransform(scaleTransform);
        painter.setPen(Qt::red);
        painter.drawText(100, 60, "Scaled Rect");
        painter.drawRect(100, 70, 50, 30);

        // 恢复状态
        painter.restore();
        painter.save();

        // 4. 旋转变换
        QTransform rotateTransform;
        rotateTransform.translate(200, 100); // 先平移到 (200, 100)
        rotateTransform.rotate(45); // 绕 Z 轴旋转 45 度
        painter.setTransform(rotateTransform);
        painter.setPen(Qt::green);
        painter.drawText(0, -10, "Rotated Rect");
        painter.drawRect(0, 0, 50, 30);

        // 恢复状态
        painter.restore();
        painter.save();

        // 5. 剪切变换
        QTransform shearTransform;
        shearTransform.shear(0.2, 0.1); // X 轴剪切因子 0.2,Y 轴剪切因子 0.1
        painter.setTransform(shearTransform);
        painter.setPen(Qt::magenta);
        painter.drawText(20, 120, "Sheared Rect");
        painter.drawRect(20, 130, 50, 30);

        // 恢复状态
        painter.restore();
        painter.save();

        // 6. 自定义矩阵变换
        QTransform matrixTransform;
        matrixTransform.setMatrix(1, 0.2, 0, 0.1, 1, 0, 50, 50, 1); // 自定义 3x3 矩阵
        painter.setTransform(matrixTransform);
        painter.setPen(Qt::cyan);
        painter.drawText(0, -10, "Custom Matrix Rect");
        painter.drawRect(0, 0, 50, 30);

        // 恢复状态
        painter.restore();
        painter.save();

        // 7. 组合变换(平移 + 旋转 + 缩放)
        QTransform combinedTransform;
        combinedTransform.translate(300, 200); // 平移到 (300, 200)
        combinedTransform.rotate(30); // 旋转 30 度
        combinedTransform.scale(1.5, 1.5); // 放大 1.5 倍
        painter.setTransform(combinedTransform);
        painter.setPen(Qt::darkYellow);
        painter.drawText(0, -10, "Combined Transform Rect");
        painter.drawRect(0, 0, 50, 30);

        // 恢复状态
        painter.restore();

        // 8. 矩阵运算:组合两个变换
        QTransform t1, t2, combinedMatrix;
        t1.translate(100, 300); // 平移
        t2.rotate(30); // 旋转
        combinedMatrix = t1 * t2; // 先旋转再平移
        painter.setTransform(combinedMatrix);
        painter.setPen(Qt::darkGreen);
        painter.drawText(0, -10, "Matrix Multiplication Rect");
        painter.drawRect(0, 0, 50, 30);

        // 最终恢复状态
        painter.restore();
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    TransformWidget widget;
    widget.setWindowTitle("QTransform Demo");
    widget.show();

    return app.exec();
}

4.2、高级变换与坐标(常用于 OpenGL 相关)

4.2.1、QVector2D, QVector3D, QVector4D:向量表示

QVector2D、QVector3D 和 QVector4D 是 Qt 提供的向量类,用于表示 2D、3D 和 4D 空间中的点或向量(4D 向量常用于齐次坐标)。

  • QVector2D:在 2D/3D 空间中的点和向量,表示 2D 向量或点 (x, y)。

  • QVector3D:表示 3D 向量或点 (x, y, z)

  • QVector4D:表示 4D 向量 (x, y, z, w),常用于齐次坐标。

4.2.2、基本向量运算

  • 加法/减法:+  -

  • 标量乘法:V  * 1.0

  • 点积:v1.dotProduct(v1, v2)

  • 叉积(仅 3D): v1.crossProduct(v1, v2)

  • 长度与归一化: v.length()   v.normalized()

4.2.3、QMatrix4x4:4x4 矩阵

QMatrix4x4 是 Qt 提供的 4x4 矩阵类,广泛用于 3D 变换和 OpenGL 渲染。它支持齐次坐标,能够表示复杂的 3D 变换(包括透视投影)。

4.2.3.1 理解齐次坐标与 4x4 矩阵在 2D/3D 变换中的作用

  • 齐次坐标:

    • 在 2D 中,点 (x, y) 表示为 (x, y, 1)。

    • 在 3D 中,点 (x, y, z) 表示为 (x, y, z, 1)。

    • 齐次坐标允许平移、旋转、缩放等变换通过矩阵乘法统一处理。

  • 4x4 矩阵:

    • 用于表示 3D 空间中的所有仿射变换和投影变换。

    • 矩阵形式:

      [ m11  m12  m13  m14 ]
      [ m21  m22  m23  m24 ]
      [ m31  m32  m33  m34 ]
      [ m41  m42  m43  m44 ]
    • 通常 m44 = 1,m14, m24, m34 = 0(仿射变换)。

  • 平移:matrix.translate(10.0, 20.0, 30.0); // 平移 (10, 20, 30)

  • 缩放:matrix.scale(2.0, 0.5, 1.0); // X 放大 2 倍,Y 缩小 0.5 倍,Z 不变

  • 旋转:matrix.rotate(45.0, 0, 0, 1); // 绕 Z 轴旋转 45 度

  • 透视投影:matrix.perspective(60.0, 4.0/3.0, 0.1, 100.0); // 视场角 60 度,宽高比 4:3,近裁面 0.1,远裁面 100。

4.2.3.2、在 OpenGL 渲染中

QMatrix4x4 常用于:

  • 模型变换:将物体从模型坐标转换为世界坐标。

  • 视图变换:将世界坐标转换为相机坐标。

  • 投影变换:将 3D 场景投影到 2D 屏幕。

4.2.4、示例代码

#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QMatrix4x4>
#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
#include <QTimer>
#include <QDebug>

// 自定义 OpenGL 窗口部件,用于展示向量和矩阵操作
class OpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions {
    Q_OBJECT
public:
    OpenGLWidget(QWidget *parent = nullptr) : QOpenGLWidget(parent) {
        // 设置定时器以实现动画效果
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, [this]() { this->update(); });
        timer->start(16); // 约 60 FPS
    }

protected:
    // 初始化 OpenGL 环境
    void initializeGL() override {
        initializeOpenGLFunctions(); // 初始化 OpenGL 函数

        // 设置着色器程序
        m_program = new QOpenGLShaderProgram(this);
        // 顶点着色器:处理顶点位置并应用 MVP 矩阵
        m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,
            "#version 330 core\n"
            "layout(location = 0) in vec3 vertexPos;\n"
            "uniform mat4 mvp;\n"
            "void main() {\n"
            "    gl_Position = mvp * vec4(vertexPos, 1.0);\n"
            "}"
        );
        // 片段着色器:设置固定颜色(青色)
        m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,
            "#version 330 core\n"
            "out vec4 fragColor;\n"
            "void main() {\n"
            "    fragColor = vec4(0.0, 0.8, 0.8, 1.0);\n"
            "}"
        );
        m_program->link(); // 链接着色器
        m_program->bind(); // 绑定着色器

        // 定义简单立方体的顶点(8 个顶点)
        GLfloat vertices[] = {
            // 前表面
            -0.5f, -0.5f,  0.5f,  // 左下
             0.5f, -0.5f,  0.5f,  // 右下
             0.5f,  0.5f,  0.5f,  // 右上
            -0.5f,  0.5f,  0.5f,  // 左上
            // 后表面
            -0.5f, -0.5f, -0.5f,  // 左下
             0.5f, -0.5f, -0.5f,  // 右下
             0.5f,  0.5f, -0.5f,  // 右上
            -0.5f,  0.5f, -0.5f   // 左上
        };

        // 定义立方体的索引(12 个三角形)
        GLushort indices[] = {
            0, 1, 2, 2, 3, 0,  // 前表面
            1, 5, 6, 6, 2, 1,  // 右表面
            5, 4, 7, 7, 6, 5,  // 后表面
            4, 0, 3, 3, 7, 4,  // 左表面
            3, 2, 6, 6, 7, 3,  // 上表面
            4, 5, 1, 1, 0, 4   // 下表面
        };

        // 创建并绑定顶点缓冲对象 (VBO) 和索引缓冲对象 (IBO)
        glGenBuffers(1, &m_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glGenBuffers(1, &m_ibo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

        // 设置顶点属性
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
        glEnableVertexAttribArray(0);

        // 启用深度测试
        glEnable(GL_DEPTH_TEST);
        // 设置背景颜色(深灰色)
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    }

    // 处理窗口大小调整
    void resizeGL(int w, int h) override {
        glViewport(0, 0, w, h); // 设置视口
        m_projection.setToIdentity(); // 重置投影矩阵
        // 设置透视投影:60° 视场角,宽高比,近裁面 0.1,远裁面 100
        m_projection.perspective(60.0f, static_cast<float>(w) / h, 0.1f, 100.0f);
    }

    // 绘制场景
    void paintGL() override {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色和深度缓冲
        m_program->bind(); // 绑定着色器程序

        // 演示向量操作
        demonstrateVectorOperations();

        // 设置变换矩阵
        QMatrix4x4 model, view;
        model.setToIdentity(); // 初始化模型矩阵
        view.setToIdentity();  // 初始化视图矩阵

        // 模型变换:平移、旋转、缩放
        model.translate(0.0f, 0.0f, -5.0f); // 将立方体沿 Z 轴向后移动 5 单位
        model.rotate(m_rotationAngle, 1.0f, 1.0f, 0.0f); // 绕 (1,1,0) 轴旋转
        model.scale(1.5f, 1.5f, 1.5f); // 放大 1.5 倍

        // 视图变换:设置相机位置
        view.translate(0.0f, 0.0f, -5.0f); // 相机沿 Z 轴后移 5 单位

        // 组合矩阵:模型-视图-投影 (MVP)
        QMatrix4x4 mvp = m_projection * view * model;
        m_program->setUniformValue("mvp", mvp); // 传递 MVP 矩阵给着色器

        // 绘制立方体
        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, nullptr);

        m_program->release(); // 释放着色器程序

        // 更新旋转角度以实现动画
        m_rotationAngle += 1.0f;
        if (m_rotationAngle >= 360.0f) m_rotationAngle -= 360.0f;
    }

private:
    // 演示向量操作
    void demonstrateVectorOperations() {
        // 2.1.1 向量创建
        QVector2D v2d(3.0f, 4.0f); // 2D 向量 (3, 4)
        QVector3D v3d(1.0f, 2.0f, 3.0f); // 3D 向量 (1, 2, 3)
        QVector4D v4d(1.0f, 2.0f, 3.0f, 1.0f); // 4D 齐次坐标向量 (1, 2, 3, 1)

        // 2.1.2 向量运算
        // 加法
        QVector3D v3d2(4.0f, 5.0f, 6.0f);
        QVector3D sum = v3d + v3d2; // 结果:(5, 7, 9)
        qDebug() << "向量加法:" << sum.x() << sum.y() << sum.z();

        // 标量乘法
        QVector3D scaled = v3d * 2.0f; // 结果:(2, 4, 6)
        qDebug() << "标量乘法:" << scaled.x() << scaled.y() << scaled.z();

        // 点积
        float dot = QVector3D::dotProduct(v3d, v3d2); // 1*4 + 2*5 + 3*6 = 32
        qDebug() << "点积:" << dot;

        // 叉积
        QVector3D cross = QVector3D::crossProduct(v3d, v3d2);
        qDebug() << "叉积:" << cross.x() << cross.y() << cross.z();

        // 长度与归一化
        float length = v3d.length(); // 计算向量长度
        QVector3D normalized = v3d.normalized(); // 归一化向量
        qDebug() << "长度:" << length << "归一化:" << normalized.x() << normalized.y() << normalized.z();
    }

    QOpenGLShaderProgram *m_program; // 着色器程序
    GLuint m_vbo, m_ibo; // 顶点缓冲对象和索引缓冲对象
    QMatrix4x4 m_projection; // 投影矩阵
    float m_rotationAngle = 0.0f; // 旋转角度
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 创建并显示 OpenGL 窗口
    OpenGLWidget widget;
    widget.setWindowTitle("QMatrix4x4 和 QVector 演示");
    widget.resize(800, 600); // 设置窗口大小
    widget.show();

    return app.exec();
}

#include "main.moc"



5、与 UI 集成:在控件上绘图说明

5.1、QWidget 的 paintEvent()

paintEvent() 是 QWidget 类中的一个虚拟函数,当控件需要重绘时由 Qt 的事件循环自动调用。它是控件进行自定义绘图的主要入口点。

Qt 会在以下情况下触发 paintEvent():

  • 控件首次显示时。

  • 控件被调整大小、移动或显示状态改变时。

  • 控件被其他窗口遮挡后重新暴露出来。

  • 开发者手动调用 update() 或 repaint() 请求重绘。

实现方式

  • 重写 QWidget 或其子类的 paintEvent() 函数。

  • 在函数中使用 QPainter 进行绘图操作。

  • paintEvent() 由 Qt 的事件循环调用,开发者不应直接调用它。

5.2、在 paintEvent() 中使用 QPainter

QPainter 是 Qt 的核心绘图类,用于在 paintEvent() 中执行具体的绘图操作。它提供了一套丰富的 API,用于绘制基本几何形状、文本、图像以及处理变换、抗锯齿等。

使用步骤

  • 创建 QPainter 对象:将 QWidget 指针(通常是 this)传递给 QPainter 构造函数,使其绑定到当前控件。

  • 配置绘图属性:

    • 设置画笔(QPen):控制线条颜色、宽度、样式等。

    • 设置画刷(QBrush):控制填充颜色、渐变、图案等。

    • 启用抗锯齿:painter.setRenderHint(QPainter::Antialiasing);

    • 设置变换:支持平移、旋转、缩放等。

  • 执行绘图操作:

    • 绘制基本形状:drawLine()、drawRect()、drawEllipse() 等。

    • 绘制文本:drawText()。

    • 绘制图像:drawPixmap()、drawImage()。

  • 自动清理:QPainter 对象在离开作用域时会自动销毁,释放资源。

高级特性

  • 裁剪区域:使用 painter.setClipRect() 或 painter.setClipRegion() 限制绘图区域,仅绘制需要更新的部分,提升性能。

  • 坐标变换:使用 painter.translate()、painter.rotate()、painter.scale() 实现复杂的图形变换。

  • 抗锯齿:通过 setRenderHint(QPainter::Antialiasing) 改善绘制质量,适合绘制曲线或斜线。

  • 渐变填充:使用 QLinearGradient、QRadialGradient 等实现平滑的颜色过渡。

5.3、更新控件:update()、repaint()

它们都会导致 paintEvent() 被调用,但使用场景和行为有所不同。

5.3.1、update():请求异步重绘控件,将重绘事件放入 Qt 的事件队列,稍后由事件循环处理。

  • 特点:

    • 异步操作,多个 update() 调用可能被合并为一次重绘,减少不必要的绘制。

    • 适合大多数场景,如控件内容发生变化(例如用户交互、数据更新)时。

    • 不会立即触发 paintEvent(),延迟较小但性能更高。

  • 使用场景:

    • 数据更新后需要刷新界面。

    • 响应用户输入(如鼠标点击后更新选中状态)。

5.3.2、repaint():请求同步重绘控件,立即调用 paintEvent()。

  • 特点:

    • 同步操作,会立刻触发重绘,可能导致性能开销。

    • 不会合并多次调用,每次调用都会触发一次完整重绘。

    • 适合需要立即刷新的场景,但应谨慎使用以避免频繁调用。

  • 使用场景:

    • 实时动画或快速更新的图形(如动态波形图)。

    • 需要立即看到绘制结果的调试场景。

5.3.3、update() vs repaint()

特性

update()

repaint()

调用方式

异步,放入事件队列

同步,立即执行

性能

高,合并多次调用

较低,每次调用都重绘

使用场景

常规更新,响应用户交互

实时动画,立即刷新

延迟

可能有微小延迟

无延迟

5.4、双缓冲绘图以减少闪烁

闪烁(flickering)是指控件重绘时出现短暂的空白或不完整画面,通常在复杂绘图或频繁更新时发生。

5.4.1、双缓冲原理

  • 双缓冲:在内存中维护一个与控件大小相同的缓冲区(后台缓冲),所有绘图操作先在缓冲区中完成,然后将缓冲区内容一次性绘制到屏幕上(前台缓冲)。

    • 避免了绘图过程中屏幕上出现不完整的中间状态。

    • 提高了绘图的流畅性,减少闪烁。

  • Qt 的 QWidget 默认启用双缓冲,开发者无需手动管理缓冲区。

5.4.2、默认双缓冲行为

  • 在 paintEvent() 中,QPainter 自动将绘图操作应用到后台缓冲区。

  • 绘制完成后,Qt 将后台缓冲区的内容复制到屏幕。

  • 这一过程对开发者透明,无需额外代码。

5.4.3、优化双缓冲以减少闪烁

尽管 Qt 默认启用了双缓冲,但在某些情况下仍可能出现闪烁。以下是优化建议:

  • 避免不必要的重绘:

    • 使用 update() 而非 repaint(),以合并多次重绘请求。

    • 仅在内容实际改变时调用 update(),避免重复调用。

  • 限制重绘区域:

    • 在 paintEvent() 中检查 QPaintEvent::rect() 或 QPaintEvent::region(),仅绘制受影响的区域。

    • 使用 QPainter::setClipRect() 裁剪绘图区域。

  • 使用 QPixmap 进行预渲染:

    • 对于静态或变化不频繁的内容,预先将绘图结果渲染到 QPixmap,然后在 paintEvent() 中直接绘制 QPixmap。

    • 适合复杂的图形或需要重复绘制的场景。

  • 禁用不必要的背景擦除:

    • 默认情况下,Qt 会在绘制前擦除控件的背景,可能导致闪烁。

    • 通过设置 Qt::WA_OpaquePaintEvent 属性,告诉 Qt 控件会完全绘制其区域,无需擦除背景。

  • 启用硬件加速:

    • 如果绘图性能瓶颈明显,可考虑使用 QOpenGLWidget 替代 QWidget,利用 GPU 加速渲染。

    • 注意硬件加速可能增加复杂性,需确保目标平台支持 OpenGL。

5.4.4、示例代码

QWidget 的 paintEvent():

  • 重写了 paintEvent(),用于绘制静态内容(鼠标点击的圆点、网格线)和动态内容(旋转矩形)。

  • 使用 QPainter 进行绘图,结合 setClipRect() 限制重绘区域,优化性能。

在 paintEvent() 中使用 QPainter:

  • 启用了抗锯齿(setRenderHint(QPainter::Antialiasing))以提高绘制质量。

  • 使用 translate() 和 rotate() 实现旋转矩形的动画效果。

  • 绘制多种元素:圆点(drawEllipse)、矩形(drawRect)、文本(drawText)、网格线(drawLine)。

更新控件:update(), repaint():

  • 鼠标点击时调用 update(),异步更新静态内容(圆点)。

  • 定时器触发时调用 repaint(),同步更新动态内容(旋转矩形),确保动画流畅。

  • 通过检查数据变化(m_buffer.isNull())避免不必要的重绘。

双缓冲绘图以减少闪烁:

  • 使用 QPixmap m_buffer 作为后台缓冲区,预渲染静态内容(圆点和网格线)。

  • 在 paintEvent() 中,将缓冲区内容绘制到控件上,仅更新受影响区域(event->rect())。

  • 设置 Qt::WA_OpaquePaintEvent 属性,禁用背景擦除,减少闪烁。

  • 控件大小变化时(resizeEvent),清空缓冲区以适应新尺寸。

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
#include <QTimer>
#include <QList>
#include <QPoint>

class CustomWidget : public QWidget {
    Q_OBJECT
public:
    CustomWidget(QWidget *parent = nullptr) : QWidget(parent) {
        // 启用双缓冲和优化属性
        setAttribute(Qt::WA_OpaquePaintEvent); // 禁用背景擦除,减少闪烁
        setMouseTracking(true); // 启用鼠标跟踪

        // 启动定时器,每50ms更新一次,用于动画
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, &CustomWidget::onTimerUpdate);
        timer->start(50);

        // 初始化旋转角度
        m_angle = 0;

        // 初始化缓冲区
        m_buffer = QPixmap();
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        // 如果缓冲区无效或大小不匹配,重新绘制
        if (m_buffer.isNull() || m_buffer.size() != size()) {
            m_buffer = QPixmap(size());
            m_buffer.fill(Qt::white); // 设置背景色

            QPainter bufferPainter(&m_buffer);
            bufferPainter.setRenderHint(QPainter::Antialiasing); // 启用抗锯齿

            // 绘制静态内容:鼠标点击的圆点
            bufferPainter.setPen(Qt::blue);
            bufferPainter.setBrush(Qt::yellow);
            for (const QPoint &point : m_points) {
                bufferPainter.drawEllipse(point, 5, 5);
            }

            // 绘制网格线(示例静态内容)
            bufferPainter.setPen(QPen(Qt::gray, 1, Qt::DashLine));
            for (int x = 0; x < width(); x += 50) {
                bufferPainter.drawLine(x, 0, x, height());
            }
            for (int y = 0; y < height(); y += 50) {
                bufferPainter.drawLine(0, y, width(), y);
            }
        }

        // 在控件上绘制缓冲区内容
        QPainter painter(this);
        painter.setClipRect(event->rect()); // 限制绘制区域,优化性能
        painter.drawPixmap(event->rect(), m_buffer, event->rect());

        // 绘制动态内容:旋转矩形(不使用缓冲区)
        painter.setRenderHint(QPainter::Antialiasing);
        painter.translate(width() / 2, height() / 2); // 平移到控件中心
        painter.rotate(m_angle); // 应用旋转
        painter.setPen(Qt::red);
        painter.setBrush(Qt::green);
        painter.drawRect(-25, -25, 50, 50); // 绘制旋转矩形

        // 绘制提示文本
        painter.resetTransform(); // 重置变换
        painter.setPen(Qt::black);
        painter.drawText(10, 20, "Click to add points, animation runs automatically");
    }

    void mousePressEvent(QMouseEvent *event) override {
        // 记录鼠标点击位置并请求重绘
        if (event->button() == Qt::LeftButton) {
            m_points.append(event->pos());
            m_buffer = QPixmap(); // 清空缓冲区,强制重新绘制
            update(); // 异步更新
        }
    }

    void resizeEvent(QResizeEvent *event) override {
        // 控件大小变化时清空缓冲区
        m_buffer = QPixmap();
        update();
    }

private slots:
    void onTimerUpdate() {
        // 更新旋转角度并立即重绘(适合动画)
        m_angle += 5;
        if (m_angle >= 360) m_angle -= 360;
        repaint(); // 同步更新以确保动画流畅
    }

private:
    QList<QPoint> m_points; // 存储鼠标点击位置
    QPixmap m_buffer; // 双缓冲区
    qreal m_angle; // 旋转角度
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 创建并显示自定义控件
    CustomWidget widget;
    widget.setWindowTitle("Custom Drawing Example");
    widget.resize(400, 300);
    widget.show();

    return app.exec();
}

#include "main.moc" // 包含 moc 文件以支持 Qt 的信号槽机制

三. 图像处理

支持图像创建、操作和文件读写。

  • QImage: 像素级图像操作,适合图像处理。

  • QPixmap: 优化用于屏幕显示的图像。

  • QBitmap: 单色位图。

  • QPicture: 记录和重放绘图指令。

  • QImageReader, QImageWriter: 图像文件读写(支持 PNG、JPEG 等格式)。

  • QMovie: 动态图像播放(如 GIF)。

  • QImageIOHandler: 自定义图像格式处理。

  • QImageEncoderSettings, QImageDecoder (Qt 6): 图像编码/解码设置。

四. 字体和文本

提供字体管理和低级文本渲染功能。

  • QFont: 字体属性管理(大小、粗细、样式)。

  • QFontMetrics, QFontMetricsF: 字体度量,计算文本尺寸。

  • QFontDatabase: 系统字体资源访问。

  • QTextLayout, QTextOption: 高级文本布局和格式化。

  • QRawFont: 直接访问字体文件数据。

  • QTextFragment, QTextBlock: 低级文本结构(用于复杂文本渲染)。

  • QGlyphRun: 字形级文本渲染。

五. 事件和输入处理

处理 GUI 相关的用户输入和交互事件。

  • QMouseEvent: 鼠标点击、移动事件。

  • QHoverEvent: 鼠标悬停事件。

  • QWheelEvent: 鼠标滚轮事件。

  • QKeyEvent: 键盘输入事件。

  • QTouchEvent: 触摸输入事件。

  • QNativeGestureEvent: 平台特定手势(如 macOS 手势)。

  • QInputMethod, QInputMethodEvent: 输入法支持(虚拟键盘、语言切换)。

  • QDrag, QDropEvent: 拖放操作。

  • QClipboard: 剪贴板访问。

  • QTabletEvent: 数位板输入事件。

  • QEnterEvent (Qt 6): 鼠标进入/离开事件。

  • QExposeEvent: 窗口暴露事件。

  • QPlatformDrag: 平台特定的拖放实现。

六. OpenGL 和硬件加速

支持 OpenGL 和 Vulkan 渲染,适用于高性能图形。

  • QOpenGLContext: OpenGL 上下文管理。

  • QOpenGLFunctions, QOpenGLExtraFunctions: OpenGL API 封装。

  • QOpenGLFramebufferObject: 帧缓冲对象,用于离屏渲染。

  • QOpenGLShader, QOpenGLShaderProgram: 着色器支持。

  • QOpenGLTexture: 纹理管理。

  • QOpenGLBuffer: 顶点和索引缓冲区。

  • QOpenGLVertexArrayObject: 顶点数组对象。

  • QOpenGLTimerQuery, QOpenGLTimeMonitor: OpenGL 性能监控。

  • QAbstractOpenGLFunctions (Qt 6): 抽象化的 OpenGL 函数接口。

  • QVulkanInstance, QVulkanWindow (Qt 6): Vulkan 渲染支持。

七. 颜色和外观

管理颜色和外观设置。

  • QColor: 颜色表示(支持 RGB、HSV、CMYK)。

  • QPalette: 颜色方案管理(前景、背景等)。

  • QColorSpace (Qt 6): 颜色空间管理(支持 ICC 配置文件)。

  • QColormap: 颜色映射(主要用于旧平台)。

八. 图标和光标

支持图标和鼠标光标管理。

  • QIcon: 图标管理,支持多分辨率和状态。

  • QCursor: 鼠标光标样式和自定义形状。

  • QIconEngine: 自定义图标渲染引擎。

九. 平台和渲染后端

提供平台特定集成和渲染后端支持。

  • QPlatformIntegration: 平台特定的窗口系统集成(Windows、X11、Wayland 等)。

  • QRasterPaintEngine: 软件光栅化渲染引擎。

  • QPlatformSurface: 平台特定的渲染表面。

  • QPlatformTheme: 平台主题(如按钮样式、对话框风格)。

  • QPlatformGraphicsBuffer: 平台特定的图形缓冲区。

  • QPlatformSharedGraphicsCache: 共享图形缓存,加速渲染。

十. 国际化(GUI 相关)

支持 GUI 相关的字符编码和区域设置。

  • QTextCodec(部分):字符编码支持(仅限 GUI 文本显示)。

  • QLocale(部分):区域设置(仅限 GUI 格式,如日期、数字显示)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭唐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值