前言

完整代码:QT实现汽车仪表盘完整代码

一、汽车仪表盘示例

用 QT 实现汽车仪表盘如下:

汽车仪表盘.gif

该示例主要用到了 QPaintEvent 绘图事件,QPainter 的使用。

QPaintEvent 是 Qt 框架中一个重要的事件类,专门用于处理绘图事件。当 Qt 视图组件需要重绘自己的一部分时,就会产生 QPaintEvent 事件。

QPainter 是 Qt 库中用于在屏幕上进行绘画的类。它提供了各种绘制功能,比如画线、画图形、画文本等。

接下来我将一步一步实现该汽车仪表盘。

二、实现代码框架

实现汽车仪表盘,我们可以从两个方面入手,先实现静态界面如仪表盘刻度和数字:

image.png

再实现动态界面如速度显示和UI美化:

image.png

1. 静态界面实现

静态界面实现步骤如下:

  1. 初始化画布
  2. 画小圆
  3. 画刻度
  4. 画刻度文字

1.1 初始化画布

实现步骤:

  1. 重写 paintEvent
  2. 设置分辨率为 800 * 600
  3. 将底色设置为黑色
  4. 将坐标系移到正中间偏下一点的位置(方便后面设置刻度)

代码示例:

protected:
    void paintEvent(QPaintEvent *event) override;
    
private:
    void initCanvas(QPainter& painter); // 初始化画布

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 设置分辨率为800*600
    setFixedSize(800,600); 
}
    
void Widget::initCanvas(QPainter& painter)
{
   // 启用抗锯齿
   painter.setRenderHint(QPainter::Antialiasing, true);

   // 设置底色为黑色
   painter.setBrush(Qt::black);
   painter.drawRect(rect());

   // 设置坐标系为中心偏下一点
   QPoint cent(rect().width() / 2, rect().height() * 0.6);
   painter.translate(cent);
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    
    // 初始化画布
    initCanvas(painter);
}

在这里我们使用 painter.setRenderHint(QPainter::Antialiasing, true); 可以启用抗锯齿功能,这样在使用 QPainter 进行绘图时,绘制的线条、曲线和文本等会具有更平滑的边缘,提高图像的质量和美观度。

程序运行效果如下:

image.png

坐标轴分析:

image.png

1.2 画小圆

实现步骤:

  1. 设置画笔为白色,像素为3
  2. 画小圆

代码示例:

private:
    void drawMiddleCircle(QPainter& painter,int radius); // 画小圆

void Widget::drawMiddleCircle(QPainter &painter, int radius)
{
    // 设置画笔颜色为白色,像素为3
    painter.setPen(QPen(Qt::white, 3));

    // 以坐标为(0,0),x 为 radius,y 为 radius 画椭圆(x = y 时为画圆)
    painter.drawEllipse(QPoint(0, 0), radius, radius);
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);
    
    // 画小圆
    drawMiddleCircle(painter, 60);
}

程序运行效果如下:
image.png

1.3 画刻度

实现步骤:

  1. 保存原来坐标位置
  2. 旋转坐标轴,画刻度
  3. 恢复原来坐标位置

代码示例:

private:
    int startAngle;
    double angle;
    
    void drawScale(QPainter& painter,int radius); // 画刻度

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    startAngle = 150;
}

void Widget::drawScale(QPainter &painter, int radius)
{
    angle = 240 * 1.0 / 60;

    // 保存原来坐标位置
    painter.save();
    painter.setPen(QPen(Qt::white, 5));

    // 旋转坐标轴
    painter.rotate(startAngle);

    // 画刻度
    for (int i = 0; i <= 60; i++)
    {
        if (i >= 40)
        {
            painter.setPen(QPen(Qt::red, 5));
        }
        if (i % 5 == 0)
        {
            painter.drawLine(radius -20, 0, radius - 3, 0);
        }
        else
        {
            painter.drawLine(radius -8, 0, radius - 3, 0);
        }
        painter.rotate(angle);
    }

    // 恢复原来坐标位置
    painter.restore();
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);

    // 画小圆
    drawMiddleCircle(painter, 60);

    // 画刻度
    drawScale(painter, rad);
}

程序运行效果如下:

在这里插入图片描述

坐标轴分析:初始化旋转150°后到达0刻度线位置

image.png

1.4 画刻度文字

实现步骤:

  1. 设置绘图字体样式
  2. 保存坐标系
  3. 算出平移坐标点
  4. 平移坐标系
  5. 旋转坐标系
  6. 绘制文字
  7. 恢复坐标系

代码示例:

private:
    void drawScaleText(QPainter& painter,int radius); // 画刻度文字


#include <QtMath>

void Widget::drawScaleText(QPainter &painter, int radius)
{
    // 设置绘图字体样式
    QFont font("Arial", 15);

    // 设置粗体
    font.setBold(true);
    painter.setFont(font);

    int r = radius - 50;

    for (int i = 0; i <= 60; i++)
    {
        if (i % 5 == 0)
        {
            // 保存坐标系
            painter.save();

            //算出平移点,弧度=角度*3.1415/180
            int x = qCos((210-angle * i) * M_PI / 180) * r;
            int y = qSin(qDegreesToRadians(210 - angle * i)) * r; // QT中Sin和Cos默认是弧度

            // 平移坐标系
            painter.translate(QPoint(x, -y));

            // 旋转坐标系
            painter.rotate(-120+angle*i);//angle=4,30*4=120的时候,实参是0,120

            // 写上文字
            painter.drawText(-25, -25, 50, 30, Qt::AlignCenter, QString::number(i * 4));
            // 恢复坐标系
            painter.restore();
        }
    }
}

计算平移点解析:

image.png

在 QT 中 Sin 和 Cos 默认是弧度,我们可以用 QT 中数学库自带的函数转换
qDegreesToRadians:将度数转化为弧度

也可以通过数学公式自行计算:弧度 = 角度 * 3.1415 / 180

image.png

程序运行效果如下:

image.png

2. 动态界面实现

动态界面实现步骤如下:

  1. 画指针
  2. 画扇形
  3. 画渐变内圈圆
  4. 画黑色内圈
  5. 设置当前速度
  6. 画外环发光圈
  7. 画一个汽车logo

2.1 画指针

实现步骤:

  1. 保存坐标系
  2. 设置画刷和画笔
  3. 设置多边形的四个顶点坐标
  4. 旋转画笔
  5. 绘制多边形
  6. 恢复坐标系
  7. 开始定时器,旋转指针

代码示例:

private:
    int currentValue;
    int mark = 0;
    
    void drawPointLine(QPainter &painter,int lenth); // 画指针
    void startSpeed(); // 开启定时器,旋转指针


#include <QTimer>

void Widget::drawPointLine(QPainter &painter, int lenth)
{
    // 保存坐标系
    painter.save();

    painter.setBrush(Qt::white);
    
    // 将画笔设置为无边框
    painter.setPen(Qt::NoPen);

    // 设置多边形四个顶点坐标
    static const QPointF points[4] = {
        QPointF(0, 0.0),
        QPointF(200.0, -1.1),
        QPointF(200.0, 1.1),
        QPointF(0, 15.0),
    };

    // 旋转画笔
    painter.rotate(startAngle + angle * currentValue);

    // 绘制多边形
    painter.drawPolygon(points, 4);

    // 恢复坐标系
    painter.restore();
}

void Widget::startSpeed()
{
    timer = new QTimer(this);

    currentValue = 0;

    connect(timer, &QTimer::timeout, [=]() {
        if (mark == 0)
        {
            currentValue++;
            if (currentValue >= 61)
            {
                mark = 1;
            }
        }
        if (mark == 1)
        {
            currentValue--;
            if (currentValue == 0)
            {
                mark = 0;
            }
        }
        update();
    });

    timer->start(50);
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);

    // 画小圆
    drawMiddleCircle(painter, 60);

    // 画刻度
    drawScale(painter, rad);

    // 画刻度文字
    drawScaleText(painter, rad);

    // 画指针
    drawPointLine(painter, rad - 58);
}

程序运行效果如下:

image.png

2.2 画扇形

实现步骤:

  1. 设置矩形边框
  2. 设置画笔和画刷
  3. 画扇形

代码示例:

private:
    void drawSpeedPie(QPainter& painter,int radius); // 画扇形

void Widget::drawSpeedPie(QPainter &painter, int radius)
{
    // 1. 设置矩形边框
    QRect rentangle(-radius, -radius, radius * 2, radius * 2);

    // 2. 设置画笔和画刷
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(255, 0, 0, 80));

    // 3. 画扇形
    painter.drawPie(rentangle, (360 - startAngle) * 16, -angle * currentValue * 16);
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);

    // 画小圆
    drawMiddleCircle(painter, 60);

    // 画刻度
    drawScale(painter, rad);

    // 画刻度文字
    drawScaleText(painter, rad);

    // 画指针
    drawPointLine(painter, rad - 58);

    // 画扇形
    drawSpeedPie(painter, rad+25);
}

setBrush(QColor(255, 0, 0, 80))方法将画刷设置为半透明的红色,其中RGB值为(255, 0, 0)表示红色,最后一个参数80表示透明度,范围为0(完全透明)到255(完全不透明)。

程序运行效果如下:

image.png

2.3 画渐变内圈圆

画渐变内圈圆主要用到 QRadialGradient 类,QRadialGradient 是 Qt 框架中用于创建径向渐变的类。

径向渐变是一种从中心点向外部辐射的颜色渐变,通常在中心点有一种颜色,而向外围渐渐变化为另一种颜色。这种渐变非常适合用于模拟光源、阴影或创建圆形的立体感。

实现步骤:

  1. 创建 QRadialGradient 对象:指定渐变的中心点、半径
  2. 设置颜色停靠点:在径向渐变中定义颜色和对应的位置
  3. 使用渐变创建画刷
  4. 绘制内圈圆

代码示例:

private:
    void drawEllipseInnerShine(QPainter& painter,int radius); // 画渐变内圈圆

void Widget::drawEllipseInnerShine(QPainter &painter, int radius)
{
    // 1. 创建 QRadialGradient 对象:指定渐变的中心点、半径
    QRadialGradient radialGradient(0, 0, radius);

    // 2. 设置颜色停靠点:在径向渐变中定义颜色和对应的位置
    radialGradient.setColorAt(0, QColor(255, 0, 0, 200));
    radialGradient.setColorAt(1, QColor(0, 0, 0, 100));

    // 3. 使用渐变创建画刷
    painter.setBrush(radialGradient);

    // 4. 绘制内圈圆
    painter.drawEllipse(QPoint(0, 0), radius, radius);
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);

    // 画小圆
    drawMiddleCircle(painter, 60);

    // 画刻度
    drawScale(painter, rad);

    // 画刻度文字
    drawScaleText(painter, rad);

    // 画指针
    drawPointLine(painter, rad - 58);

    // 画扇形
    drawSpeedPie(painter, rad+25);

    // 画渐变内圈圆
    drawEllipseInnerShine(painter,100);
}

程序运行效果如下:

image.png

2.4 画黑色内圈圆

实现步骤:

  1. 设置画刷
  2. 绘制内圈圆

代码示例:

private:
    void drawEllipseInnerBlack(QPainter& painter,int radius);  // 画黑色内圈圆

    
void Widget::drawEllipseInnerBlack(QPainter &painter, int radius)
{
    // 1. 设置画刷
    painter.setBrush(Qt::black);

    // 2. 绘制内圈圆
    painter.drawEllipse(QPoint(0, 0), radius, radius);
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);

    // 画小圆
    drawMiddleCircle(painter, 60);

    // 画刻度
    drawScale(painter, rad);

    // 画刻度文字
    drawScaleText(painter, rad);

    // 画指针
    drawPointLine(painter, rad - 58);

    // 画扇形
    drawSpeedPie(painter, rad+25);

    // 画渐变内圈圆
    drawEllipseInnerShine(painter,100);

    // 画黑色内圈圆
    drawEllipseInnerBlack(painter, 70);
}

程序运行效果如下:

image.png

2.5 设置当前速度

实现步骤:

  1. 设置画笔
  2. 设置绘图字体样式
  3. 绘制速度
  4. 绘制单位

代码示例:

private:
    void drawCurrentSpeed(QPainter& painter); // 设置当前速度

void Widget::drawCurrentSpeed(QPainter &painter)
{
    // 1. 设置画笔
    painter.setPen(Qt::white);
    
    // 2. 设置绘图字体样式
    QFont font1("Arial", 30);
    font1.setBold(true);
    painter.setFont(font1);
    
    // 3. 绘制速度
    painter.drawText(QRect(-60, -60, 120, 70), Qt::AlignCenter, QString::number(currentValue * 4));

    // 4. 绘制单位 Km/h (同上)
    QFont font2("Arial", 13);
    font2.setBold(true);
    painter.setFont(font2);
    painter.drawText(QRect(-60, -60, 120, 160), Qt::AlignCenter, "Km/h");

}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);

    // 画小圆
    drawMiddleCircle(painter, 60);

    // 画刻度
    drawScale(painter, rad);

    // 画刻度文字
    drawScaleText(painter, rad);

    // 画指针
    drawPointLine(painter, rad - 58);

    // 画扇形
    drawSpeedPie(painter, rad+25);

    // 画渐变内圈圆
    drawEllipseInnerShine(painter,100);

    // 画黑色内圈圆
    drawEllipseInnerBlack(painter, 70);

    // 设置当前速度
    drawCurrentSpeed(painter);
}

程序运行效果如下:

image.png

2.6 画外环发光圈

实现步骤:

  1. 设置矩形边框
  2. 将画笔设置为无边框
  3. 创建 QRadialGradient 对象:指定渐变的中心点、半径
  4. 设置颜色停靠点:在径向渐变中定义颜色和对应的位置
  5. 使用渐变创建画刷
  6. 绘制扇形

代码示例:

private:
    void drawEllipseOutterShine(QPainter& painter,int radius); // 画外环发光圈

void Widget::drawEllipseOutterShine(QPainter &painter, int radius)
{
    // 1. 设置矩形边框
    QRect rentangle(-radius, -radius, radius * 2, radius * 2);

    // 2. 将画笔设置为无边框
    painter.setPen(Qt::NoPen);

    // 3. 创建 QRadialGradient 对象:指定渐变的中心点、半径
    QRadialGradient radialGradient(0, 0, radius);

    // 4. 设置颜色停靠点:在径向渐变中定义颜色和对应的位置
    radialGradient.setColorAt(1, QColor(255, 0, 0, 200));
    radialGradient.setColorAt(0.97, QColor(255, 0, 0, 120));
    radialGradient.setColorAt(0.9, QColor(255, 0, 0, 0));
    radialGradient.setColorAt(0, QColor(255, 0, 0, 0));

    // 5. 使用渐变创建画刷
    painter.setBrush(radialGradient);

    // 6. 绘制扇形
    painter.drawPie(rentangle, (360 - 150) * 16, -angle * 61 * 16);
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);

    // 画小圆
    drawMiddleCircle(painter, 60);

    // 画刻度
    drawScale(painter, rad);

    // 画刻度文字
    drawScaleText(painter, rad);

    // 画指针
    drawPointLine(painter, rad - 58);

    // 画扇形
    drawSpeedPie(painter, rad+25);

    // 画渐变内圈圆
    drawEllipseInnerShine(painter,100);

    // 画黑色内圈圆
    drawEllipseInnerBlack(painter, 70);

    // 设置当前速度
    drawCurrentSpeed(painter);

    // 画外环发光圈
    drawEllipseOutterShine(painter,rad+25);
}

程序运行效果如下:

image.png

2.7 画一个汽车logo

实现步骤:

  1. 设置矩形边框
  2. 绘制资源图片

添加图片资源:

image.png

image.png

image.png

image.png

image.png

代码示例:

private:
    void drawLogo(QPainter& painter, int radius);  // 画汽车logo

void Widget::drawLogo(QPainter &painter, int radius)
{
    // 1. 设置矩形边框
    QRect rectangle(-65, radius * 0.38, 130, 50);

    // 2. 绘制资源图片
    painter.drawPixmap(rectangle,QPixmap(":/icon.png"));
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int rad = height() / 2;

    // 初始化画布
    initCanvas(painter);

    // 画小圆
    drawMiddleCircle(painter, 60);

    // 画刻度
    drawScale(painter, rad);

    // 画刻度文字
    drawScaleText(painter, rad);

    // 画指针
    drawPointLine(painter, rad - 58);

    // 画扇形
    drawSpeedPie(painter, rad+25);

    // 画渐变内圈圆
    drawEllipseInnerShine(painter,100);

    // 画黑色内圈圆
    drawEllipseInnerBlack(painter, 70);

    // 设置当前速度
    drawCurrentSpeed(painter);

    // 画外环发光圈
    drawEllipseOutterShine(painter,rad+25);

    // 画一个汽车logo
    drawLogo(painter, rad);
}

程序运行效果如下:

image.png

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐