Qt 仪表盘源码分享

发布于:2025-06-06 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、效果展示

在这里插入图片描述

二、优点

  1. 直观性

    • 数据以图表或数字形式展示,一目了然。
    • 用户可以快速获取关键信息,无需深入阅读大量文字。
  2. 实时性

    • 仪表盘通常支持实时更新,确保数据的时效性。
    • 有助于及时发现和解决问题,提高决策效率。
  3. 可定制性

    • 用户可以根据需要选择显示哪些指标和数据。
    • 支持个性化设置,满足不同用户的特定需求。
  4. 易用性

    • 界面设计友好,操作简单。
    • 即使是技术背景不强的用户也能轻松上手。
  5. 多维度分析

    • 可以同时展示多个维度的数据,便于综合分析。
    • 提供多种视图和过滤选项,帮助用户从不同角度理解数据。
  6. 可视化效果

    • 利用图表、颜色等视觉元素,增强数据的表现力。
    • 帮助用户更直观地识别趋势和异常。

三、源码分享

dashboardWidget.h

#ifndef DASHBOARD_H
#define DASHBOARD_H

#include <QWidget>
#include <QPainter>
#include <QFontMetricsF>

class DashboardWidget : public QWidget
{
    Q_OBJECT
public:
    explicit DashboardWidget(QWidget *parent = nullptr);

    void paintEvent(QPaintEvent *evt);
    void setCurrentValue(float value)
    {
        this->currentValue = value;
        this->update();
    }
    float getCurrentValue()
    {
        return this->currentValue;
    }
    void setRange(int min,int max)
    {
        this->minVal = min;
        this->maxValue = max;
        update();
    }
    void setRedScale(int value)
    {
        this->redScale = value;
    }
    void setUnit(QString value)
    {
        this->unit = value;
    }


private:
    void drawBg(QPainter *painter);
    void drawDial(QPainter *painter);
    void drawScaleNum(QPainter *painter);
    void drawIndicator(QPainter *painter);
    void drawText(QPainter *painter);
signals:

private:
    int radius;     //半径
    int startAngle;     //表盘起始角度
    int minVal,maxValue;//表盘数字起始值和结束值
    int redScale;//红色刻度开始值
    float currentValue;  //当前值
    QString unit;

};

#endif // DASHBOARD_H

dashboardWidget.cpp

#include "dashboardWidget.h"

DashboardWidget::DashboardWidget(QWidget *parent)
    : QWidget{parent}
{
    setAttribute(Qt::WA_TranslucentBackground, true);
    this->setStyleSheet("background-color: rgba(255, 255, 255, 0);");
    radius = 100;
    startAngle = 45;
    currentValue = 0;
    minVal = 0;
    maxValue = 100;
    redScale = 80;
    unit = nullptr;
}

void DashboardWidget::paintEvent(QPaintEvent *evt)
{
    Q_UNUSED(evt);
    int width = this->width();
    int height = this->height();

    //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.translate(width / 2, height / 2);

    int side = qMin(width, height);
    painter.scale(side / 200.0, side / 200.0);


    //绘制最外框圆形背景
    drawBg(&painter);
     //绘制刻度
     drawDial(&painter);
     //绘制刻度数值
     drawScaleNum(&painter);
     //绘制指针
     drawIndicator(&painter);
     //绘制表盘上文本当前值
     drawText(&painter);


}

void DashboardWidget::drawBg(QPainter *painter)
{
    int r = radius;
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(QColor(172, 172, 172));
    painter->drawEllipse(-r, -r, r * 2, r * 2);

    r =  radius * 0.9;
    painter->setBrush(QColor(40, 40, 40));
    painter->setPen(Qt::NoPen);
    painter->drawEllipse(-r, -r, r * 2, r * 2);
    painter->restore();

}

void DashboardWidget::drawDial(QPainter *painter)
{
    int r = radius*0.85;
    double lineWidth = 1;
    painter->save();

    painter->rotate(startAngle);
    /*
    为什么旋转?
    如果不旋转画笔的坐标轴,那么每次画的时候需要按照角度来重新计算,x=r*cos,y=r*sin. 计算复杂
    但是如果旋转坐标轴,那么首次旋转angle角度,则y轴和第一条斜线重合,x=0,只需要计算y。
    画100条线,就是分100份来表示进度。每次旋转的角度=360-(起始角度*2--分左右)/100
    */
    double rotate = (double)(360 - (startAngle * 2)) / 100;
    int valTotal = abs(minVal)+abs(maxValue);
    float valToAngle = (float)valTotal/100;

    for (int i = 0; i <= 100; i++) {
        QColor color = QColor(84, 84, 84);
        float redScaleStartVal = this->minVal+i*valToAngle;
        if(redScaleStartVal>=this->redScale) color = QColor(250, 0, 0);
        if((i % 10) == 0)
        {
            painter->setPen(QPen(color, 1.3*lineWidth));
            painter->drawLine(0, r, 0, r / 1.2);
        }
        else if((i % 2) == 0)
        {
            painter->setPen(QPen(color, 1*lineWidth));
            painter->drawLine(0, r, 0, r / 1.1);
        }
        painter->rotate(rotate);
    }

    painter->restore();

}

void DashboardWidget::drawScaleNum(QPainter *painter)
{
    painter->save();

    int r = (int)(radius*0.6);

    painter->setFont(QFont("Arial", 10));
    painter->setPen(QPen(QColor(255,255,255)));
    QFontMetricsF fm = QFontMetricsF(painter->font());

    int gap = (360-startAngle*2) / 10;

    int valGap = abs(minVal)+abs(maxValue);
    valGap/=10;

    int refreshVal = minVal;
    for(int i=0; i<=10; i+=1)
    {
        int angle = 90+startAngle+gap*i;  //角度,10格子画一个刻度值

        float angleArc =( angle % 360) * 3.14 / 180; //转换为弧度
        int x = (r)*cos(angleArc);
        int y = (r)*sin(angleArc);

        QString value = QString::number(refreshVal);
        refreshVal += valGap;
        int w = (int)fm.averageCharWidth()*value.length();
        int h = (int)fm.height();
        x = x - w/2;
        y = y + h/4;

        //painter->drawPoint(QPointF(x, y));
        painter->drawText(QPointF(x, y),value);
    }
    painter->restore();

}

void DashboardWidget::drawIndicator(QPainter *painter)
{
    painter->save();
    QPolygon pts;
    pts.setPoints(3, -2, 0, 2, 0, 0, 60);

    painter->rotate(startAngle);
    float degRotate = (270.0f  / (this->maxValue - this->minVal)) * (currentValue - this->minVal);

    //画指针
    painter->rotate(degRotate);
    QRadialGradient haloGradient(0, 0, 60, 0, 0);
    haloGradient.setColorAt(0, QColor(160, 160, 160).lighter(100));
    haloGradient.setColorAt(1, QColor(160, 160, 160));
    painter->setPen(QColor(255, 255, 255));
    painter->setBrush(haloGradient);
    painter->drawConvexPolygon(pts);
    painter->restore();

    //画中心点
    painter->save();
    QConicalGradient coneGradient(0, 0, -90.0);
    coneGradient.setColorAt(0.0, QColor(65, 65, 65));
    coneGradient.setColorAt(0.5, QColor(255, 255, 255));
    coneGradient.setColorAt(1.0, QColor(65, 65, 65));
    painter->setPen(Qt::NoPen);
    painter->setBrush(coneGradient);
    painter->drawEllipse(-5, -5, 10, 10);
    painter->restore();

}

void DashboardWidget::drawText(QPainter *painter)
{
    //绘制单位
    painter->save();

    painter->setFont(QFont("Arial", 14));
    painter->setPen(QPen(QColor(255,255,255)));
    QFontMetricsF fmUnit = QFontMetricsF(painter->font());
    int unitW = (int)fmUnit.averageCharWidth()*this->unit.length();
   // int unitH = (int)fmUnit.height();
    painter->drawText(QPointF(-unitW/2, (int)(0.3*radius)),this->unit);


    //绘制字符

    painter->setFont(QFont("Arial", 10));
    painter->setPen(QPen(QColor(255,255,255)));
    QFontMetricsF fm = QFontMetricsF(painter->font());
    QString speed = QString::number(currentValue,'f',1) + this->unit;
    int w = (int)fm.averageCharWidth()*speed.length();
    //int h = (int)fm.height();
    painter->drawText(QPointF(-w/2, (int)(0.5*radius)),speed);

    painter->restore();

}

四、使用方法

放置一个QWidget
然后右键提升
在这里插入图片描述
选择仪表盘类就OK!


网站公告

今日签到

点亮在社区的每一天
去签到