Qt 仪表盘源码分享

article/2025/6/7 14:27:17

Qt 仪表盘源码分享

  • 一、效果展示
  • 二、优点
  • 三、源码分享
  • 四、使用方法

一、效果展示

在这里插入图片描述

二、优点

  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!


http://www.hkcw.cn/article/AxkbuSUCAA.shtml

相关文章

吞咽与营养并重:进行性核上性麻痹的饮食之道

进行性核上性麻痹是一种罕见的神经系统变性疾病&#xff0c;患者常出现吞咽困难、肢体运动障碍等症状&#xff0c;合理饮食对改善患者营养状况、延缓病情发展至关重要。以下为进行性核上性麻痹患者量身定制的健康饮食方案。 ​患者饮食需遵循 “细软易消化、均衡营养、少食多餐…

leetcode hot100 链表(二)

书接上回&#xff1a; leetcode hot100 链表&#xff08;一&#xff09;-CSDN博客 8.删除链表的倒数第N个结点 class Solution { public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* currhead;int len0;while(curr){currcurr->next;len;}int poslen-n…

结构性设计模式之Composite(组合)

结构性设计模式之Composite&#xff08;组合&#xff09; 摘要&#xff1a; Composite&#xff08;组合&#xff09;模式通过树形结构表示"部分-整体"层次关系&#xff0c;使得用户能够统一处理单个对象和组合对象。该模式包含Component&#xff08;组件接口&#x…

【Typst】4.导入、包含和读取

概述 上节概述了Typst脚本的基础语法&#xff0c;在此基础上&#xff0c;本节介绍Typst文件的导入、包含和读取的内容。你将可以更简单灵活的组织你的文件内容。 系列目录 1.Typst概述2.Typst标记语法和基础样式3.Typst脚本语法4.导入、包含和读取5.文档结构元素与函数6.布局…

深入解析C++引用:从别名机制到函数特性实践

1.C引用 1.1引用的概念和定义 引用不是新定义⼀个变量&#xff0c;而是给已存在变量取了⼀个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同⼀块内存空间。比如四大名著中林冲&#xff0c;他有一个外号叫豹子头&#xff0c;类比到C里就…

【vue+ts】找不到模块“./App.vue”或其相应的类型声明

报错&#xff1a;找不到模块“./App.vue”或其相应的类型声明。 原因&#xff1a;typescript只能理解.ts文件&#xff0c;无法理解.vue文件。 解决&#xff1a;在src/env.d.ts下添加&#xff1a; /// <reference types"vite/client" /> // 三斜线引用告诉编译…

HTTP Error 400 Bad request 问题分析解决

文章目录 1.问题描述&#xff1a;2.异常信息如下&#xff1a;3.分析异常信息&#xff1a;4.总结&#xff1a; 1.问题描述&#xff1a; 前端保存老是报错HTTP ERROR 400 Bad Request。经过异常分析得出是前端传参导致的后端框架的验证拦截&#xff0c;包的错误。 2.异常信息如下…

数据库的操作

1.查看数据库 show databases; 2.库的创建 create database [IF NOT EXITS] db_name [creat_specification];[]内的是可选选项&#xff0c;IF NOT EXIT表示如果数据库名为db_name的数据库存在就创建数据库&#xff0c;否则就不创建&#xff0c;creat_specification是创建的特…

IP话机和APP拨打电话的区别

‌IP话机和IP电话App&#xff08;如Zoom Phone、Microsoft Teams、Skype等&#xff09;均基于互联网协议&#xff08;VoIP&#xff09;技术实现通话&#xff0c;但在硬件形态、使用场景、功能侧重等方面存在显著差异。以下是主要区别&#xff1a; 1. 硬件形态与部署 IP话机 物…

el-select 实现分页加载,切换也数滚回到顶部,自定义高度

el-select 实现分页加载&#xff0c;切换也数滚回到顶部&#xff0c;自定义高度 1.html <el-form-item label"俱乐部&#xff1a;" prop"club_id" label-width"120px"><el-select :disabled"Boolean(match_id)" style"w…

帝可得- 人员管理

一.需求说明 人员管理业务流程如下&#xff1a; 登录系统&#xff1a; 首先&#xff0c;后台管理人员需要登录到帝可得后台管理系统中。 新增工作人员&#xff1a; 登录系统后&#xff0c;管理人员可以新增工作人员&#xff0c;包括姓名、联系方式等信息。 关联角色&#xf…

【Java Web】7.事务管理AOP

&#x1f4d8;博客主页&#xff1a;程序员葵安 &#x1faf6;感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb; 文章目录 一、事务管理 1.1 事务回顾 1.2 Spring事务管理 1.3 事务进阶 rollbackFor propagation 二、AOP 2.1 AOP概述 2.2 AOP快速入门…

Matlab实现LSTM-SVM回归预测,作者:机器学习之心

Matlab实现LSTM-SVM回归预测&#xff0c;作者&#xff1a;机器学习之心 目录 Matlab实现LSTM-SVM回归预测&#xff0c;作者&#xff1a;机器学习之心效果一览基本介绍程序设计参考资料 效果一览 基本介绍 代码主要功能 该代码实现了一个LSTM-SVM回归预测模型&#xff0c;核心流…

【开源工具】Python+PyQt5打造智能桌面单词记忆工具:悬浮窗+热键切换+自定义词库

&#x1f4da;【深度解析】PythonPyQt5打造智能桌面单词记忆工具&#xff1a;悬浮窗热键切换自定义词库 &#x1f308; 个人主页&#xff1a;创客白泽 - CSDN博客 &#x1f525; 系列专栏&#xff1a;&#x1f40d;《Python开源项目实战》 &#x1f4a1; 热爱不止于代码&#x…

第二十二章 Shell脚本入门

第二十二章 Shell脚本入门 Shell脚本就是包含一系列命令的文件。Shell读取该文件并执行其中的命令&#xff0c;Shell的独特之处在于它即使系统强大的命令接口&#xff0c;又是脚本语言解释器。 创建并执行Shell脚本 创建并执行脚本&#xff0c;要做到3件事: 编写脚本。将脚…

Pandas取代Excel?

有人在知乎上提问&#xff1a;为什么大公司不用pandas取代excel&#xff1f; 而且列出了几个理由&#xff1a;Pandas功能比Excel强大&#xff0c;运行速度更快&#xff0c;Excel除了简单和可视化界面外&#xff0c;没有其他更多的优势。 有个可怕的现实是&#xff0c;对比Exce…

网络安全运维实训室建设方案

一、网络安全运维人才需求与实训困境 在数字化时代&#xff0c;网络安全已成为国家安全、社会稳定和经济发展的重要基石。随着信息技术的飞速发展&#xff0c;网络安全威胁日益复杂多样&#xff0c;从个人隐私泄露到企业商业机密被盗&#xff0c;从关键基础设施遭受攻击到社会…

【C++篇】STL适配器(下篇):优先级队列与反向迭代器的底层奥秘

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对C感兴趣的…

在使用十字滑台的过程中,我们需要注意哪些关键事项呢

在使用十字滑台的过程中&#xff0c;需要注意以下关键事项&#xff1a; 安全操作&#xff1a;在使用十字滑台时&#xff0c;务必要注意安全&#xff0c;戴好手套和护目镜&#xff0c;避免发生意外伤害。 稳定支撑&#xff1a;确保十字滑台稳固地放置在平坦稳定的表面上&#x…

【笔记】用命令手动下载并安装 tokenizers 库.whl文件(Python 3.12+)

Python 3.12 虚拟环境中安装 tokenizers 教程笔记 在 Python 3.12 虚拟环境中安装 tokenizers 库时&#xff0c;我们可能会遇到pip install tokenizers安装失败和找不到适配版本的公开 whl 文件&#xff0c;从而导致tokenizers库缺失的问题。 经过探索&#xff0c;我们找到了…