QT:paintEvent、QPainter、QPaintDevice

embedded/2025/2/26 7:47:44/

paintEvent 介绍

在 Qt 编程中,paintEvent 是 QWidget 类中的一个非常重要的虚函数,用于处理绘图事件。当一个 QWidget 或其派生类的实例需要进行重绘操作时,Qt 会自动调用该控件的 paintEvent 函数。

触发时机

窗口首次显示:当一个窗口或控件第一次显示在屏幕上时,会触发 paintEvent 来绘制其初始外观。
窗口大小改变:当用户调整窗口大小,或者通过代码改变窗口大小时,为了适应新的尺寸,会触发 paintEvent 重新绘制内容。
窗口被遮挡后恢复显示:如果窗口被其他窗口遮挡,之后遮挡窗口移开,窗口需要重新绘制可见部分,此时会触发 paintEvent。
调用 update() 或 repaint() 方法:在代码中调用 update() 或 repaint() 方法可以手动触发 paintEvent。update() 会在 Qt 的事件循环中安排一次重绘,它会合并多个 update() 调用以避免不必要的重绘;而 repaint() 会立即触发重绘操作。

void QWidget::paintEvent(QPaintEvent *event);

QPaintEvent *event 是一个指向 QPaintEvent 对象的指针,该对象包含了与绘制事件相关的信息,例如需要重绘的区域(通过 event->rect() 可以获取)。

响应窗口大小变化

#include <QApplication>
#include <QWidget>
#include <QPainter>class ResizableWidget : public QWidget {
public:ResizableWidget(QWidget *parent = nullptr) : QWidget(parent) {}protected:void paintEvent(QPaintEvent *event) override {Q_UNUSED(event);QPainter painter(this);// 绘制一个与窗口大小相关的矩形int x = width() / 4;int y = height() / 4;int w = width() / 2;int h = height() / 2;painter.drawRect(x, y, w, h);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);ResizableWidget widget;widget.setWindowTitle("Resizable Drawing");widget.resize(300, 300);widget.show();return app.exec();
}

定义了 ResizableWidget 类,重写 paintEvent 函数。
在 paintEvent 中,根据窗口的当前宽度和高度计算矩形的位置和大小,然后绘制矩形。这样当窗口大小改变时,矩形会自动调整以适应新的窗口尺寸。
在这里插入图片描述

QPainter

QPainter 是 Qt 框架中用于执行 2D 绘图操作的核心类。它提供了丰富的 API,允许开发者在各种 QPaintDevice(如画布、窗口、图像等)上绘制基本图形(如点、线、矩形、椭圆等)、文本、图像,还能应用渐变、变换等效果,从而实现复杂的图形和界面绘制。

QPainter 的主要特点和功能包括:

基本图形绘制:支持绘制点、线、矩形、椭圆、多边形等多种基本图形。
文本绘制:可以在指定位置绘制文本,并能设置字体、颜色、对齐方式等属性。
图像绘制:能够将图像绘制到指定位置,还可以进行缩放、旋转等操作。
渐变填充:支持线性渐变、径向渐变、锥形渐变等填充效果。
变换操作:如平移、旋转、缩放等,可对绘制的图形进行变换。
抗锯齿:可以开启抗锯齿功能,使绘制的图形边缘更加平滑。

绘制基本图形

#include <QApplication>
#include <QWidget>
#include <QPainter>class DrawingWidget : public QWidget {
protected:void paintEvent(QPaintEvent *event) override {Q_UNUSED(event);QPainter painter(this);// 绘制直线painter.drawLine(20, 20, 200, 20);// 绘制矩形painter.drawRect(20, 40, 180, 100);// 绘制椭圆painter.drawEllipse(20, 160, 180, 100);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);DrawingWidget widget;widget.setWindowTitle("Basic Shapes Drawing");widget.resize(300, 300);widget.show();return app.exec();
}

在这里插入图片描述

DrawingWidget 类继承自 QWidget,并重写了 paintEvent 方法,在该方法中进行绘图操作。
QPainter 对象 painter 用于实际的绘图,它以 this(即 DrawingWidget 实例)作为绘图设备。
drawLine 方法用于绘制直线,传入起点和终点的坐标。
drawRect 方法绘制矩形,参数分别为矩形左上角的坐标以及矩形的宽度和高度。
drawEllipse 方法绘制椭圆,参数与矩形类似。

绘制文本

#include <QApplication>
#include <QWidget>
#include <QPainter>class TextDrawingWidget : public QWidget {
protected:void paintEvent(QPaintEvent *event) override {Q_UNUSED(event);QPainter painter(this);// 设置字体QFont font("Arial", 20);painter.setFont(font);// 设置文本颜色painter.setPen(Qt::blue);// 绘制文本painter.drawText(50, 100, "Hello, Qt!");}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);TextDrawingWidget widget;widget.setWindowTitle("Text Drawing");widget.resize(300, 300);widget.show();return app.exec();
}

创建 QFont 对象设置字体的名称和大小,并通过 setFont 方法将其应用到 QPainter 上。
setPen 方法设置文本的颜色为蓝色。
drawText 方法在指定位置绘制文本,第一个参数是文本左上角的横坐标,第二个参数是纵坐标,第三个参数是要绘制的文本内容。

在这里插入图片描述

变换操作

#include <QApplication>
#include <QWidget>
#include <QPainter>class TransformationWidget : public QWidget {
protected:void paintEvent(QPaintEvent *event) override {Q_UNUSED(event);QPainter painter(this);// 保存当前的绘图状态painter.save();// 平移坐标系painter.translate(width() / 2, height() / 2);// 旋转坐标系painter.rotate(45);// 绘制旋转后的矩形painter.drawRect(-50, -25, 100, 50);// 恢复之前保存的绘图状态painter.restore();}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);TransformationWidget widget;widget.setWindowTitle("Transformation Drawing");widget.resize(300, 300);widget.show();return app.exec();
}

save 方法保存当前的绘图状态,包括坐标系、画笔、画刷等属性。
translate 方法将坐标系原点平移到窗口的中心。
rotate 方法将坐标系旋转 45 度。
绘制矩形时,使用的是平移和旋转后的坐标系。
restore 方法恢复之前保存的绘图状态,以便后续绘图不受影响。
在这里插入图片描述

QPaintDevice

QPaintDevice 是 Qt 中所有可以进行绘制操作的对象的基类,它为 QPainter 提供了一个绘图的目标设备抽象接口。也就是说,QPainter 可以在任何继承自 QPaintDevice 的对象上进行绘图操作,比如窗口、图像、打印机等。

主要特点

抽象性:QPaintDevice 是一个抽象基类,不能直接实例化,它定义了一些纯虚函数,这些函数由具体的子类来实现,从而实现不同类型设备的绘图功能。
多设备支持:Qt 提供了多个继承自 QPaintDevice 的子类,常见的有 QWidget(用于窗口和控件)、QImage(用于内存中的图像)、QPixmap(用于屏幕优化的图像)、QPrinter(用于打印机)等,这使得开发者可以在不同的设备上进行统一的绘图操作。
与 QPainter 协作:QPainter 是绘图的执行者,而 QPaintDevice 是绘图的目标,二者紧密协作完成绘图任务。在使用 QPainter 进行绘图时,需要在构造函数中传入一个 QPaintDevice 对象作为参数。

常用子类及用途

QWidget:用于创建窗口和各种用户界面控件,QWidget 的 paintEvent 函数中通常会使用 QPainter 在窗口上进行绘图。
QImage:可以在内存中创建和操作图像,它支持直接访问像素数据,适合进行图像处理和生成图像文件。
QPixmap:是一种专门为屏幕显示优化的图像表示,它可以高效地在屏幕上绘制,常用于快速显示图像。
QPrinter:用于将绘图内容输出到打印机,实现打印功能。

在 QWidget 上绘图

#include <QApplication>
#include <QWidget>
#include <QPainter>class DrawingWidget : public QWidget {
public:DrawingWidget(QWidget *parent = nullptr) : QWidget(parent) {}protected:void paintEvent(QPaintEvent *event) override {Q_UNUSED(event);QPainter painter(this);  // this 是 QWidget 对象,作为 QPaintDevicepainter.setPen(Qt::blue);painter.drawLine(20, 20, 200, 20);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);DrawingWidget widget;widget.setWindowTitle("Drawing on QWidget");widget.resize(300, 200);widget.show();return app.exec();
}

在这里插入图片描述
定义了一个自定义的 DrawingWidget 类,继承自 QWidget。
在 paintEvent 函数中,创建了一个 QPainter 对象,将 this(即 DrawingWidget 实例,它是 QWidget 类型,继承自 QPaintDevice)作为绘图设备。
使用 QPainter 的 setPen 方法设置画笔颜色为蓝色,然后调用 drawLine 方法在窗口上绘制一条直线

在 QImage 上绘图并保存为文件

在这里插入图片描述

#include <QApplication>
#include <QImage>
#include <QPainter>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建一个 QImage 对象作为绘图设备QImage image(200, 200, QImage::Format_RGB32);image.fill(Qt::white);  // 填充背景为白色QPainter painter(&image);  // 将 QImage 作为绘图设备painter.setPen(Qt::red);painter.drawRect(50, 50, 100, 100);painter.end();  // 结束绘图// 保存图像为文件image.save("output.png", "PNG");return app.exec();
}

创建了一个 QImage 对象,指定了图像的宽度、高度和像素格式。
使用 fill 方法将图像背景填充为白色。
创建 QPainter 对象,将 QImage 对象的指针作为绘图设备传入。
使用 QPainter 的 setPen 方法设置画笔颜色为红色,然后调用 drawRect 方法在图像上绘制一个矩形。
调用 end 方法结束绘图操作。
最后使用 save 方法将绘制好的图像保存为 output.png 文件。

使用 QPrinter 打印图形

QT       += core gui printsupport
#include <QApplication>
#include <QPrinter>
#include <QPainter>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建一个 QPrinter 对象QPrinter printer;printer.setOutputFormat(QPrinter::PdfFormat);printer.setOutputFileName("output.pdf");// 创建 QPainter 对象,将 QPrinter 作为绘图设备QPainter painter(&printer);painter.setPen(Qt::green);painter.drawEllipse(50, 50, 100, 100);painter.end();return app.exec();
}

创建了一个 QPrinter 对象,并设置输出格式为 PDF,指定输出文件名为 output.pdf。
创建 QPainter 对象,将 QPrinter 对象的指针作为绘图设备传入。
使用 QPainter 的 setPen 方法设置画笔颜色为绿色,然后调用 drawEllipse 方法绘制一个椭圆。
调用 end 方法结束绘图操作,此时绘制的内容会被输出到指定的 PDF 文件中。

在这里插入图片描述


http://www.ppmy.cn/embedded/167228.html

相关文章

Log | Hugo+PaperMod+Github创建自己的博客网站

0. 友情提示 以上内容是我根据我的博客构建内容中总结&#xff0c;并不是在构建过程中记录的&#xff0c;或许有错误之处&#xff0c;若存在问题&#xff0c;欢迎大家指出&#xff01; 欢迎大家关注我的个人博客网站&#xff1a;YHs Log 1. 引言 Lilian Wengs Log: LilLog 在…

大模型在尿潴留风险预测及围手术期方案制定中的应用研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 研究方法与数据来源 二、大模型预测尿潴留的原理与方法 2.1 相关大模型介绍 2.2 模型构建与训练 2.3 模型评估指标与验证 三、术前尿潴留风险预测及方案制定 3.1 术前风险因素分析 3.2 大模型预测结果分析 3.3 …

【解决idea2024.3.3版本Vue插件报错】

解决idea2024.3.3版本Vue插件报【Vue: TypeError: ctxVars.at is not a function at forEachInterpolationSegment】错 错误关键信息[Vue: TypeError: ctxVars.at is not a function at forEachInterpolationSegment]注&#xff1a;本文中文件路径为我们自己安装idea的实际路径…

数据分析七大步骤

在工作中&#xff0c;我们可能都遭遇过面对一堆数据&#xff0c;费尽心思进行分析&#xff0c;结果却惨不忍睹&#xff0c;仿佛“一顿操作猛如虎&#xff0c;一看结果0:5”。更糟糕的是&#xff0c;有时我们甚至完全找不到数据分析的头绪。 别急&#xff0c;朋友们&#xff01…

GB 44497-2024《智能网联汽车 自动驾驶数据记录系统》标准解读

GB 44497-2024《智能网联汽车 自动驾驶数据记录系统》是由工业和信息化部提出并归口的强制性国家标准&#xff0c;由国家市场监督管理总局、国家标准化管理委员会于2024年8月23日批准发布(国家标准公告2024年第18号文)&#xff0c;将于2026年1月1日起实施。标准规定了智能网联汽…

数据保护API(DPAPI)深度剖析与安全实践

Windows DPAPI 安全机制解析 在当今数据泄露与网络攻击日益频繁的背景下&#xff0c;Windows 提供的 DPAPI&#xff08;Data Protection API&#xff09;成为开发者保护本地敏感数据的重要工具。本文将从 双层密钥体系、加密流程、跨上下文加密、已知攻击向量与防御措施、企业…

深入理解 Kubernetes 命名空间:高效管理与隔离资源的关键

深入理解 Kubernetes 命名空间:高效管理与隔离资源的关键 目录 深入理解 Kubernetes 命名空间:高效管理与隔离资源的关键什么是命名空间?命名空间的作用1. 资源隔离2. 多租户支持3. 资源管理和策略控制4. 简化管理创建和使用命名空间命名空间与集群中的其他资源结语在 Kuber…

如何实现使用DeepSeek的CV模型对管道内模糊、低光照或水渍干扰的图像进行去噪、超分辨率重建。...

要使用 DeepSeek 的 CV 模型对管道内模糊、低光照或水渍干扰的图像进行去噪、超分辨率重建&#xff0c;一般可以按照以下步骤实现&#xff1a; 1. 准备工作 1.1 获取 API 访问权限 首先&#xff0c;你需要从 DeepSeek 官方获取 API 访问权限和相应的 API 密钥。这通常需要在 De…