一、效果展示
二、优点
直观性
- 数据以图表或数字形式展示,一目了然。
- 用户可以快速获取关键信息,无需深入阅读大量文字。
实时性
- 仪表盘通常支持实时更新,确保数据的时效性。
- 有助于及时发现和解决问题,提高决策效率。
可定制性
- 用户可以根据需要选择显示哪些指标和数据。
- 支持个性化设置,满足不同用户的特定需求。
易用性
- 界面设计友好,操作简单。
- 即使是技术背景不强的用户也能轻松上手。
多维度分析
- 可以同时展示多个维度的数据,便于综合分析。
- 提供多种视图和过滤选项,帮助用户从不同角度理解数据。
可视化效果
- 利用图表、颜色等视觉元素,增强数据的表现力。
- 帮助用户更直观地识别趋势和异常。
三、源码分享
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!