Qt 仪表盘源码分享

Qt 仪表盘源码分享

一、效果展示

二、优点

  1. 直观性

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

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

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

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

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

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

三、源码分享

dashboardWidget.h

cpp 复制代码
#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

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!

相关推荐
用户805533698033 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner3 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz8 天前
QML Hello World 入门示例
qt
xcyxiner11 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner12 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript