QT ⑤ 绘图类
一、QPaintEvent
1、QPainEvent 事件
要想实现绘图操作,就必须
重写QPainEvent事件,该事件是负责绘图的事件2、重写
//声明 void paintEvent(QPaintEvent *e); //重写画图事件 void MyPainter::paintEvent(QPaintEvent *e) { //系统默认是交给基类处理 return QWidget::paintEvent(e); }
二、QPainter
1、QPainter绘图类
QPainter是绘图类的执行类,可以设置绘图所用的QPen笔、线条等。
2、setRenderHint()
功能说明:
- 控制绘图算法的细节,如是否启用抗锯齿、文本平滑等
- 不同的渲染提示会影响绘图性能和视觉效果(通常质量越高,性能消耗略大)
常用参数(
QPainter::RenderHint):
QPainter::Antialiasing:启用抗锯齿(对线条、图形边缘效果明显)QPainter::TextAntialiasing:启用文本抗锯齿(使文字边缘更平滑)QPainter::SmoothPixmapTransform:启用图片缩放时的平滑过渡(避免失真)示例:
QPainter painter(this); // 启用抗锯齿(绘制图形更平滑) painter.setRenderHint(QPainter::Antialiasing, true); // 绘制圆形(边缘会更平滑) painter.drawEllipse(50, 50, 100, 100); // 启用文本抗锯齿 painter.setRenderHint(QPainter::TextAntialiasing, true); painter.drawText(50, 200, "平滑的文字");3、setPen(QPen)
该函数用于设置画笔
4、setBrush(QBrush)
该函数用于设置画刷
5、 QPainter::rotate()
基本功能
- 作用:以当前坐标系的原点(0,0) 为中心,将坐标系旋转指定的角度。
- 后续所有绘图操作(如
drawLine()、drawRect()等)都会在旋转后的坐标系中进行,看起来像是图形被 “旋转” 了。函数原型
void QPainter::rotate(qreal angle);
- 参数
angle:旋转角度,单位为度(°),而非弧度。
- 正数:逆时针旋转(默认方向)。
- 负数:顺时针旋转。
关键特性
旋转中心 默认以当前坐标系的原点(0,0)为旋转中心。若要围绕其他点旋转(如窗口中心),需先通过
translate(x, y)将原点移到目标点,再调用rotate()。状态累积 多次调用
rotate()会累积旋转角度。例如:painter.rotate(30); // 累计旋转30°(逆时针) painter.rotate(60); // 累计旋转90°(30+60)状态管理 旋转会改变坐标系状态,若需恢复到旋转前的状态,需配合
save()和restore()使用:
save():保存当前绘图状态(包括坐标系、画笔、画刷等)。restore():恢复到最近一次save()时的状态。6、QPainter::translate()
基本功能
- 核心作用:将当前绘图坐标系的原点(0,0) 移动到新位置,新位置相对于原原点的偏移量由参数指定。
- 对后续绘图的影响:平移后,所有绘图操作的坐标值都会以新原点为基准计算,看起来像是 “整个绘图区域被移动了”,但本质是坐标系的位置发生了改变。
函数原型
void QPainter::translate(qreal dx, qreal dy);
- 参数说明:
dx:原点在 x 轴方向的偏移量(单位:像素)。
- 正数:原点向右移动;
- 负数:原点向左移动。
dy:原点在 y 轴方向的偏移量(单位:像素)。
- 正数:原点向下移动(Qt 坐标系默认 “上为 y=0,下为 y 增大”);
- 负数:原点向上移动。
关键特性
1. 坐标系原点的 “相对性”
translate 的偏移是相对于当前原点的,而非窗口左上角。例如:
// 初始原点在窗口左上角 (0,0) painter.translate(100, 200); // 新原点 = (0+100, 0+200) = (100,200) painter.translate(50, 50); // 新原点 = (100+50, 200+50) = (150,250)2. 与其他变换的配合(核心场景)
translate 常与
rotate()(旋转)、scale()(缩放)配合,实现 “围绕任意点变换”。 典型场景:围绕窗口中心旋转图形(如时钟指针围绕中心旋转):// 步骤1:将原点平移到窗口中心(目标旋转点) painter.translate(width()/2, height()/2); // 步骤2:围绕新原点(窗口中心)旋转 painter.rotate(30); // 此时旋转中心是窗口中心,而非初始左上角 // 步骤3:绘制图形(以新原点为基准) painter.drawLine(0, 0, 100, 0); // 从中心(新原点)向右画线段3. 状态管理(save/restore)
translate 会改变坐标系状态,若需恢复到平移前的状态(避免影响后续绘图),必须配合
save()和restore():
save():保存当前绘图状态(包括坐标系、画笔、画刷等);restore():恢复到最近一次save()时的状态。7、QPainter::drawArc()
函数用于绘制椭圆弧(当宽高相等时为圆弧),其参数决定了圆弧的位置、大小和角度范围
void drawArc(int x, int y, int width, int height, int startAngle, int spanAngle);参数详解
1. 位置与大小参数(定义外接矩形)+ 角度参数(定义圆弧范围)
参数 含义 x/y外接矩形的左上角坐标(以窗口左上角为原点,x 向右递增,y 向下递增)。 width/height外接矩形的宽度和高度: - 若 width == height,绘制的是圆弧(圆的一部分); - 若width != height,绘制的是椭圆弧(椭圆的一部分)。rectQRect对象,等价于(x, y, width, height)的封装,直接定义外接矩形的位置和大小。startAngle圆弧的起始角度,单位为1/16 度(非直接度数)。 - 基准方向:3 点钟方向为 0°(即水平向右)。 - 角度递增方向:默认逆时针为正方向。 spanAngle圆弧跨越的角度范围,单位同样为1/16 度: - 正数:逆时针绘制圆弧; - 负数:顺时针绘制圆弧; - 范围限制:通常在 -360°×16 到 360°×16 之间(即完整圆的角度)。 角度转换规则:实际角度(度)需乘以 16 才能作为参数,例如:
- 90° →
90 * 16 = 1440- 180° →
180 * 16 = 2880- 360° →
360 * 16 = 5760
三、QPen
概述
QPen是 Qt 绘图系统中用于定义线条绘制属性的类,主要控制图形边缘、轮廓线的样式,如颜色、宽度、线条样式(实线、虚线等)、端点样式和连接样式等。它通常与QPainter配合使用,用于绘制直线、矩形、椭圆等图形的轮廓。常用构造函数
构造函数 说明 QPen()默认构造函数,创建黑色、1px 宽的实线画笔 QPen(const QColor &color)使用指定颜色创建画笔,默认宽度 1px,实线 常用成员函数
1. 颜色与填充相关
函数 说明 void setColor(const QColor &color)设置画笔颜色 QColor color() const获取当前画笔颜色 void setBrush(const QBrush &brush)设置画笔填充样式(可用于渐变、纹理等) QBrush brush() const获取当前画笔的填充样式 2. 线条宽度与样式
函数 说明 void setWidth(int width)设置线条宽度(整数像素) void setWidthF(qreal width)设置线条宽度(支持小数像素,更精确) int width() const/qreal widthF() const获取线条宽度 void setStyle(Qt::PenStyle style)设置线条样式(如实线、虚线等) Qt::PenStyle style() const获取当前线条样式 常用
Qt::PenStyle枚举值:
Qt::SolidLine:实线(默认)Qt::DashLine:虚线(短横线)Qt::DotLine:点线Qt::DashDotLine: dash-dot 交替线Qt::DashDotDotLine: dash-dot-dot 交替线Qt::NoPen:无线条(不绘制轮廓)3. 端点与连接样式
函数 说明 void setCapStyle(Qt::PenCapStyle cap)设置线条端点样式 Qt::PenCapStyle capStyle() const获取端点样式 void setJoinStyle(Qt::PenJoinStyle join)设置线条连接点样式(多段线拐角处) Qt::PenJoinStyle joinStyle() const获取连接点样式 常用端点样式:
Qt::SquareCap:方形端点(默认)Qt::RoundCap:圆形端点Qt::FlatCap:平端(不超出线段终点)常用连接样式:
Qt::BevelJoin:斜角连接(默认)Qt::RoundJoin:圆角连接Qt::MiterJoin:尖角连接使用示例
#include <QPainter> #include <QWidget> void MyWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter painter(this); // 创建画笔并设置属性 QPen pen; pen.setColor(Qt::blue); // 颜色 pen.setWidth(3); // 宽度 pen.setStyle(Qt::DashDotLine); // 线条样式 pen.setCapStyle(Qt::RoundCap); // 端点样式 pen.setJoinStyle(Qt::RoundJoin); // 连接样式 // 将画笔应用到 painter painter.setPen(pen); // 绘制图形(使用当前画笔) painter.drawRect(50, 50, 200, 100); // 矩形 painter.drawLine(50, 200, 250, 200); // 直线 }
四、QBrush
概述
QBrush是 Qt 绘图系统中用于定义填充区域属性的类,主要控制图形(如矩形、椭圆、多边形等)内部的填充效果,包括纯色填充、渐变填充、纹理填充等。它通常与QPainter配合使用,与QPen(控制轮廓线)共同决定图形的外观。常用构造函数
构造函数 说明 QBrush()默认构造函数,创建无填充的画刷 QBrush(Qt::GlobalColor color, Qt::BrushStyle style = Qt::SolidPattern)使用指定颜色和样式创建画刷 QBrush(const QColor &color, Qt::BrushStyle style = Qt::SolidPattern)使用 QColor 对象和样式创建画刷 QBrush(const QPixmap &pixmap)使用像素图作为纹理创建画刷 QBrush(const QGradient &gradient)使用渐变对象创建画刷 常用成员函数
1. 填充样式相关
函数 说明 void setStyle(Qt::BrushStyle style)设置填充样式 Qt::BrushStyle style() const获取当前填充样式 bool isOpaque() const判断画刷是否不透明 2. 颜色与纹理相关
函数 说明 void setColor(const QColor &color)设置画刷颜色(对纯色、渐变等样式有效) QColor color() const获取当前画刷颜色 void setTexture(const QPixmap &pixmap)设置纹理填充(使用像素图) QPixmap texture() const获取当前纹理像素图 3. 渐变相关
函数 说明 void setGradient(const QGradient &gradient)设置渐变填充 const QGradient *gradient() const获取当前渐变对象(若有) 常用枚举类型
Qt::BrushStyle(填充样式)
枚举值 说明 Qt::NoBrush无填充(透明) Qt::SolidPattern纯色填充(默认) Qt::Dense1Pattern~Qt::Dense7Pattern不同密度的点 / 线图案填充(1 最密,7 最疏) Qt::HorPattern水平线条填充 Qt::VerPattern垂直线条填充 Qt::CrossPattern十字线填充 Qt::DiagCrossPattern对角线十字填充 Qt::LinearGradientPattern线性渐变填充 Qt::RadialGradientPattern径向渐变填充 Qt::ConicalGradientPattern锥形渐变填充 Qt::TexturePattern纹理填充(使用像素图) 渐变类型(QGradient 派生类)
类名 说明 QLinearGradient线性渐变(沿直线从起点到终点过渡颜色) QRadialGradient径向渐变(从中心点向外辐射过渡颜色) QConicalGradient锥形渐变(围绕中心点旋转过渡颜色) 使用示例
#include <QPainter> #include <QWidget> #include <QLinearGradient> void MyWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter painter(this); // 1. 纯色填充 QBrush solidBrush(Qt::lightGray, Qt::SolidPattern); painter.setBrush(solidBrush); painter.drawRect(50, 50, 100, 80); // 2. 纹理填充 QBrush textureBrush(QPixmap("pattern.png")); // 使用图片作为纹理 painter.setBrush(textureBrush); painter.drawRect(200, 50, 100, 80); // 3. 线性渐变填充 QLinearGradient gradient(50, 200, 150, 280); // 从(50,200)到(150,280)的渐变 gradient.setColorAt(0, Qt::red); // 起点颜色 gradient.setColorAt(1, Qt::yellow); // 终点颜色 QBrush gradientBrush(gradient); painter.setBrush(gradientBrush); painter.drawEllipse(50, 200, 100, 80); }
五、绘制时钟示例
头文件#ifndef MYPAINTER_H #define MYPAINTER_H #include <QWidget> #include <QPaintEvent> //画图事件 #include <QPainter> //画图类 #include <QPen> //画笔类 #include <QBrush> //画刷类 #include <QRgb> //rgb颜色类 #include <QTimer> //定时器 #include <QPushButton> #include <QLabel> QT_BEGIN_NAMESPACE namespace Ui { class MyPainter; } QT_END_NAMESPACE class MyPainter : public QWidget { Q_OBJECT public: MyPainter(QWidget *parent = nullptr); ~MyPainter(); private slots: //开始计时槽函数 void startTimerSlot(); //暂停计时槽函数 void stopTimerSlot(); //计时超时 void timer_out(); private: Ui::MyPainter *ui; //重写paint事件 void paintEvent(QPaintEvent *e); //绘制时钟刻度 void painTheClock(); //绘制秒针 void painSecond(); //绘制分针 void painMinute(); //绘制时针 void painHour(); private: //开始计时按钮 QPushButton *startTimer; //暂停计时按钮 QPushButton *stopTimer; //计时显示 QLabel *label; //计时器 QTimer *timer; //秒计数器 int second = 0; }; #endif // MYPAINTER_H
实现文件#include "mypainter.h" #include "ui_mypainter.h" MyPainter::MyPainter(QWidget *parent) : QWidget(parent) , ui(new Ui::MyPainter) { //ui->setupUi(this); setFixedSize(640,480); setWindowTitle("定制时钟"); setWindowIcon(QIcon(":/favicon.ico")); setStyleSheet(QString("background-color:rgb(220, 220, 220);")); //设置背景颜色 //初始化秒数显示 label = new QLabel(this); label->setFixedSize(100,20); label->setText(QString("当前秒数: %1").arg(second)); label->move(width()-120,height()-90); //初始化开始计时按钮 startTimer = new QPushButton(this); startTimer->setText("开启计时器"); startTimer->setFixedSize(60,20); startTimer->move(width()-120,height()-60); //初始化暂停计时按钮 stopTimer = new QPushButton(this); stopTimer->setText("暂停计时器"); stopTimer->setFixedSize(60,20); stopTimer->move(width()-120,height()-30); //初始化计时器 timer = new QTimer; //绑定开始计时信号与槽 connect(startTimer , &QPushButton::clicked , this , &MyPainter::startTimerSlot); //绑定暂停计时信号与槽 connect(stopTimer , &QPushButton::clicked , this , &MyPainter::stopTimerSlot); //绑定计时器信号与槽 connect(timer , &QTimer::timeout , this , &MyPainter::timer_out); } MyPainter::~MyPainter() { //delete ui; } //开始计时 void MyPainter::startTimerSlot() { timer->start(10); //10毫秒触发一次 } //暂停计时 void MyPainter::stopTimerSlot() { timer->stop(); } //计时超时 void MyPainter::timer_out() { //qDebug() << second; this->repaint(); //重绘界面 second++; //增加秒计数 label->setText(QString("当前秒数: %1").arg(second)); //更新label显示秒数 } //绘制时钟刻度 void MyPainter::painTheClock() { //这里pain(this) 中 this 表示画图显示在哪个画图设备上,也可以显示在Pixmap或者其他画图设备上 QPainter pain(this); pain.setRenderHint(QPainter::Antialiasing,true); //启动抗锯齿 pain.translate(width() / 2, height() / 2); //确定圆心 int radius = height() / 2 - 10; //确定半径 QPen pen; //画笔类 pen.setColor(QColor(qRgb(170,255,255))); //设置颜色为rgb pen.setWidth(10); //设置画笔宽度 10px pen.setStyle(Qt::SolidLine); //设置画笔线条样式 pain.setPen(pen); //设置画笔 int i = 0; //控制变量 const int angleStep = 6; //角度步长 const int minute = 10; //分钟刻度 const int hour = 15; //小时刻度 while(i < 60){ // 保存当前绘图状态 pain.save(); // 旋转坐标系到当前刻度的角度 pain.rotate(i * angleStep); // 根据是否为小时刻度设置不同长度 和 颜色 int tickLength; if(i % 5 == 0) { pen.setColor(QColor(qRgb(255,170,255))); tickLength = hour; pain.setPen(pen); } else { pen.setColor(QColor(qRgb(170,255,255))); tickLength = minute; pain.setPen(pen); } // 绘制刻度(从圆的边缘向内绘制一条短线) pain.drawLine(radius - tickLength, 0, radius, 0); // 恢复绘图状态 pain.restore(); i++; } } //重写画图事件 void MyPainter::paintEvent(QPaintEvent *e) { //绘制时钟刻度 this->painTheClock(); //绘制时分秒针 QPainter pain(this); pain.setRenderHint(QPainter::Antialiasing,true); //启动抗锯齿 pain.translate(width() / 2, height() / 2); //确定圆心 QPen pen; //画笔类 pen.setColor(QColor(qRgb(170,170,255))); //设置颜色为rgb pen.setWidth(10); //设置画笔宽度 10px pen.setStyle(Qt::SolidLine); //设置画笔线条样式 pain.setPen(pen); //设置画笔 const int sLen = 180; //秒针长度 const int mLen = 120; //分针长度 const int hLen = 80; //时针长度 const int angleStep = 6; //角度步长 int angle = 0; //角度初始化,默认为3点钟方向 pain.save(); //保存绘图状态 //绘制秒针 angle = second * angleStep - 90; //计算秒针角度 pain.rotate(angle); //旋转角度 pain.drawLine(0,0,sLen,0); //绘制秒针 pain.rotate(-angle); //恢复角度 pain.restore(); //恢复绘图状态 pain.save(); //绘制分针 angle = second / 60 * angleStep - 90; //计算分针角度 pain.rotate(angle); //旋转角度 pain.drawLine(0,0,mLen,0); //绘制分针 pain.rotate(-angle); //恢复角度 pain.restore(); pain.save(); //绘制时针 angle = second / 720 * angleStep - 90; //计算时针角度 pain.rotate(angle); //旋转角度 pain.drawLine(0,0,hLen,0); //绘制时针 pain.restore(); }
运行截图

京公网安备 11010502036488号