1、前言
Qt绘图基础概述
Qt提供了强大的绘图功能,主要通过QPainter类实现。绘图可以在QPaintDevice的子类上进行,例如QWidget、QPixmap、QImage等。绘图操作通常在paintEvent事件中完成。
基本绘图类
- QPainter: 核心绘图工具,提供绘制线条、形状、文本和图像的方法。
- QPaintDevice : 绘图设备的基类,如
QWidget、QPixmap等。 - QPaintEngine: 底层绘图引擎,通常不需要直接使用。
- QPen: 定义绘图的线条样式、颜色和宽度。
- QBrush: 定义填充样式和颜色。
基本绘图步骤
创建QPainter对象: 在paintEvent中创建QPainter对象,并指定绘图设备:
设置绘图属性: 使用QPen和QBrush设置绘图样式:
**绘制基本图形:**绘制线条:绘制矩形:绘制椭圆:绘制文本:
坐标系统与变换
Qt的坐标系统默认以左上角为原点,X轴向右,Y轴向下。可以通过QPainter的变换方法调整坐标
自定义绘图控件
通常需要继承QWidget并重写paintEvent:
cpp
#include <QWidget>
#include <QPainter>
class MyWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *) override {
QPainter painter(this);
painter.setPen(Qt::red);
painter.setBrush(Qt::blue);
painter.drawRect(QRect(10, 10, 100, 50));
painter.drawText(QPoint(20, 30), "Qt Drawing");
}
};
QPainter提供丰富的绘图功能:
- 基本图形:
drawLine(),drawRect(),drawEllipse() - 路径绘制:
QPainterPath可创建复杂形状 - 文本绘制:
drawText() - 图像绘制:
drawImage(),drawPixmap()
通过以上方法,可以快速掌握Qt的绘图基础并实现复杂的图形界面效果。
2、立即干
1、新建绘图文件



2、添加有关属性
Q_PROPERTY 概述
Q_PROPERTY 是 Qt 框架中的一个宏,用于在类声明中定义属性(Property)。这些属性可以通过 Qt 的元对象系统(Meta-Object System)动态访问,支持信号与槽机制、属性绑定、动画等高级功能。属性通常包含一个成员变量及其对应的读写方法(Getter/Setter),并可附加元数据(如通知信号、是否可编辑等)。
cpp
Q_PROPERTY(type name
READ getter
[WRITE setter]
[RESET resetFunction]
[NOTIFY notifySignal]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
type name:属性类型和名称(如QString text)。READ getter:必须项,指定读取属性的函数(如text())。WRITE setter:可选项,指定设置属性的函数(如setText(const QString&))。NOTIFY notifySignal:可选项,指定属性变化时触发的信号(如textChanged())。
通过 Q_PROPERTY,Qt 实现了属性系统的动态性和灵活性,广泛应用于数据绑定、UI 控件属性暴露等场景

完整代码
cpp
#ifndef METER_H
#define METER_H
#include <QPaintEvent>
#include <QWidget>
class Meter : public QWidget
{
Q_OBJECT
//定义相关属性
Q_PROPERTY(qreal minimum READ minimum WRITE setMinimum);//最小值
Q_PROPERTY(qreal maximum READ maximum WRITE setMaximum);//最大值
Q_PROPERTY(double value READ value WRITE setValue);//当前值
Q_PROPERTY(QString unit READ unit WRITE setUnit);//单位
Q_PROPERTY(QString header READ header WRITE setHeader);//标题
public:
explicit Meter(QWidget *parent = nullptr);
qreal minimum() const
{
return m_minimum;
}
qreal maximum() const
{
return m_maximum;
}
double value() const
{
return m_value;
}
QString unit() const
{
return m_unit;
}
QString header() const
{
return m_header;
}
public slots:
void setMinimum(qreal minimum)
{
if(minimum==m_minimum)
return;
m_minimum = minimum;
update();
}
void setMaximum(qreal maximum)
{
if(maximum==m_maximum)
return;
m_maximum = maximum;
update();
}
void setValue(double value)
{
if(value==m_value)
return;
m_value = value;
update();
}
void setUnit(QString unit)
{
if(unit==m_unit)
return;
m_unit = unit;
update();
}
void setHeader(QString header)
{
if(header==m_header)
return;
m_header = header;
update();
}
private:
qreal m_minimum;
qreal m_maximum;
double m_value;
QString m_unit;
QString m_header;
protected:
void paintEvent(QPaintEvent *event) override;//窗体重绘事件
signals:
};
#endif // METER_H
3、绘制图形
理解 paintEvent 的基本概念
paintEvent 是 Qt 框架中 QWidget 类的一个虚函数,用于处理窗口部件的绘制事件。当部件需要重绘时(如窗口首次显示、被其他窗口遮挡后重新显示、调用 update() 或 repaint() 方法时),系统会自动调用此函数。
重写 paintEvent 的步骤
-
继承
QWidget或其子类创建一个自定义类并继承自
QWidget或其子类(如QMainWindow、QLabel等)。例如:cppclass MyWidget : public QWidget { Q_OBJECT public: explicit MyWidget(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent *event) override; };2.实现
paintEvent函数在函数内部使用
QPainter进行绘制操作。QPaintEvent参数包含需要重绘的区域信息(可通过event->rect()获取)。例如:
cpp
void MyWidget::paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.setPen(Qt::red);
painter.drawLine(0, 0, width(), height());
painter.drawText(rect(), Qt::AlignCenter, "Hello, Qt!");
}
3.触发重绘
通过调用 update() 或 repaint() 触发重绘。update() 是异步的,会将重绘请求加入事件队列;repaint() 是同步的,会立即执行重绘。
常用绘制操作
绘制基本图形
使用 QPainter 的 drawLine、drawRect、drawEllipse 等方法绘制线条、矩形、圆形等
设置画笔和画刷
QPen 用于设置线条样式,QBrush 用于设置填充样式。
通过合理使用 paintEvent,可以实现高度自定义的界面绘制效果,同时保持性能优化

完整代码
cpp
#include "meter.h"
#include <QPaintEvent>
#include <QPainter>
#include <QtMath>
Meter::Meter(QWidget *parent)
: QWidget{parent}
{
// m_maximum=100;
// m_minimum=0;
// m_value=28;
// m_unit="单位";
// m_header="温度";
}
//重绘窗体
void Meter::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QColor(0,0,0,0));
//1、渲染尺寸
int diameter=qMin(this->size().width(),this->size().height());//获取长度和宽度,取两者最小值
qreal radius=diameter/2;//圆的半径
//2、中心点
QPointF center(this->size().width()/2,this->size().height()/2);//圆心坐标
//3、底盘:径向渐变
// painter.setPen(Qt::black);
painter.setPen(Qt::transparent);//透明
QRadialGradient gradient(center.x(),center.y(),radius,center.x(),center.y());
gradient.setColorAt(0,QColor(62,155,253,60));
gradient.setColorAt(1,QColor(33,97,216,0));
painter.setBrush(gradient);
painter.drawEllipse(center,radius,radius);
//4、刻度线
int min=this->m_minimum,max=m_maximum;
int count=10,start_num=min;
// 270/100 = 2.7//刻度盘角度范围为270度
QPen pen_line(QColor("#222363DA"),2);
QPen pen_text(QColor("#992363DA"));
//循环产生刻度值,
for(int i=0;i<=100;i++){
qreal angle=i*2.7+135;//每个刻度偏转135度
painter.setPen(pen_line);
// 当i的值
int offset=7;
//每隔10个刻度线绘制一个长一点的不同颜色的刻度线
if(i%10==0){
QPen pen_line2(QColor(255,0,0,125),2);//设置颜色
painter.setPen(pen_line2);
offset=12;
}
//每隔5个刻度线绘制一个短一点的不同颜色的刻度线
else if(i%5==0)
{
QPen pen_line3(QColor(Qt::darkGreen),1);//设置颜色
painter.setPen(pen_line3);
offset=8;
}
//计算两个点的坐标值
qreal x1= center.x()+ qCos(angle*M_PI/180)*(radius-2);
qreal y1= center.y()+ qSin(angle*M_PI/180)*(radius-2);
qreal x2= center.x()+ qCos(angle*M_PI/180)*(radius-offset);
qreal y2= center.y()+ qSin(angle*M_PI/180)*(radius-offset);
painter.drawLine(QPointF(x1,y1),QPointF(x2,y2));//绘制刻度线
// 每隔10个绘制刻度值文字
if(i%10==0){
painter.setPen(pen_text);
qreal x= center.x()+ qCos(angle*M_PI/180)*(radius-22)-6;//文字X位置
qreal y= center.y()+ qSin(angle*M_PI/180)*(radius-22)+3;//文字Y位置
painter.setFont(QFont("Microsoft YaHei",9));//字体及大小
painter.drawText(QPointF(x,y),QString::number(start_num));//绘制刻度值的文字
start_num+=10;
}
}
// 指针
qreal value=this->value()-this->minimum();
qreal v_angle=value*2.7+135;
qreal p_angle_1=v_angle-90;
qreal p_angle_2=v_angle+90;
qreal x_v=qCos(v_angle*M_PI/180)*(radius-5)+center.x();
qreal y_v=qSin(v_angle*M_PI/180)*(radius-5)+center.y();
qreal x_p1=qCos(p_angle_1*M_PI/180)*2+center.x();
qreal y_p1=qSin(p_angle_1*M_PI/180)*2+center.y();
qreal x_p2=qCos(p_angle_2*M_PI/180)*2+center.x();
qreal y_p2=qSin(p_angle_2*M_PI/180)*2+center.y();
QPointF points[3]{
QPointF(x_p1,y_p1),
QPointF(x_v,y_v),
QPointF(x_p2,y_p2)
};
// 通过多边形方法进行指针的绘制(三角形)
painter.setPen(QPen(Qt::red,1));
painter.setBrush(Qt::red);
painter.drawPolygon(points,3);
// 当前数值背景圆
painter.setPen(QPen(QColor(0,0,0,33),3));
QRadialGradient gradient_center(center.x(),center.y(),20,center.x(),center.y());
gradient_center.setColorAt(0,QColor("#2F7CE9"));
gradient_center.setColorAt(1,QColor("#3E9BFC"));
painter.setBrush(gradient_center);
painter.drawEllipse(center,20,20);
// 当前值
painter.setPen(Qt::white);
painter.setFont(QFont("Microsoft YaHei",14));
painter.drawText(this->rect(),Qt::AlignCenter,QString::number(this->value()));
// 单位和标题
painter.setFont(QFont("Microsoft YaHei",8));
painter.setPen(QPen("#990146AE"));
painter.drawText(QRect(0,0,this->rect().width(),this->rect().height()-25),
Qt::AlignHCenter|Qt::AlignBottom,this->m_unit);
painter.drawText(QRect(0,0,this->rect().width(),this->rect().height()-10),
Qt::AlignHCenter|Qt::AlignBottom,this->m_header);
}
4、提升组件
提升部件概念
在Qt中,提升部件(Promoted Widgets)是一种设计时功能,允许开发者将自定义控件集成到Qt Designer中,以便在UI设计阶段直接使用。通过提升,可以将标准Qt控件(如QWidget、QLabel等)替换为自定义的子类控件。
使用场景
- 需要在Qt Designer中直接使用自定义控件。
- 避免手动编写代码替换UI文件中的标准控件。
- 简化复杂控件的可视化设计流程。
注意事项
- 提升后的控件在Qt Designer中仍显示为基类外观,但运行时会被替换为自定义控件。
- 确保头文件路径在项目配置中正确设置,否则编译时会报错。
- 若控件包含自定义属性,需通过
Q_PROPERTY声明,并在Qt Designer中通过属性编辑器调整。




这跟前面用到的将导航按钮widget提升为navbutton意思一样,提升后的控件是一个自定义控件,一定要将自定义控件编译为动态库(或确保其头文件和实现文件在项目中可访问),以便Qt Designer能识别该类。
5、运行效果

6、小结
Qt提供了强大的绘图系统,创建自定义控件需要继承QWidget并重写paintEvent方法,通过成员变量存储绘图状态,结合update()方法实现动态更新。
原创不易,打字不易,截图不易,撸码不易,整理不易,走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,灌水,请动动你的金手指,祝您早日实现财务自由。
