C++ QT 自绘表盘
文章目录
- 效果图
- 代码
效果图



代码
- 代码没什么好说的,直接上源码
- .h
#pragma once#include <QWidget>
#include <QPainter>
#include <QResizeEvent>
#include <QtMath>
#include <QCoreApplication>class DialPlateWidget : public QWidget
{Q_OBJECTQ_PROPERTY(double minValue READ getMinValue WRITE setMinValue USER true)Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue USER true)Q_PROPERTY(double value READ getValue WRITE setValue USER true)public:explicit DialPlateWidget(QWidget *parent = nullptr);// 获取和设置最小值double getMinValue() const;void setMinValue(double minValue);// 获取和设置最大值double getMaxValue() const;void setMaxValue(double maxValue);/// @brief 设置当前值void setValue(double ivalue);double getValue() const;/// @brief 设置标题和单位/// @param title/// @param unitvoid setContent(QString title, QString unit = QString());QSize sizeHint() const override;QSize minimumSizeHint() const override;~DialPlateWidget();private:void paintEvent(QPaintEvent *event) override;void drawBg(QPainter *painter);void drawDial(QPainter *painter);void drawScaleNum(QPainter *painter);void drawIndicator(QPainter *painter);void drawText(QPainter *painter);private:QString unit; // 单位QString title; // 名称const static int radius; // 半径double maxv; // 最小值double minv; // 最大值double percent = 0; // 百分比int m_refSize = 200; // 刻度线长度int Angle = 45; // 刻度线角度double m_value = 0; // 当前值
};
- cpp
#include "dialPlateWidget.h"const int DialPlateWidget::radius = 100;DialPlateWidget::DialPlateWidget(QWidget *parent) : QWidget(parent)
{maxv = 200;minv = 0;this->installEventFilter(this);m_refSize = 2.5 * radius;
}DialPlateWidget::~DialPlateWidget()
{
}void DialPlateWidget::setValue(double ivalue)
{// 确保值在最小值和最大值之间if (ivalue < minv){ivalue = minv;}else if (ivalue > maxv){ivalue = maxv;}m_value = ivalue;percent = (ivalue - minv) / (maxv - minv) * 100;update();
}double DialPlateWidget::getValue() const
{return minv + percent * (maxv - minv) / 100; // 根据百分比计算实际值
}QSize DialPlateWidget::sizeHint() const
{return QSize(m_refSize, m_refSize);
}QSize DialPlateWidget::minimumSizeHint() const
{return QSize(30, 10);
}void DialPlateWidget::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);// 计算缩放比例,确保仪表盘适应Widget大小float scale = qMin(width(), height()) / (float)m_refSize;painter.scale(scale, scale);// 设置坐标原点为中心点painter.translate(width() / (2 * scale), height() / (2 * scale));// 绘制背景、刻度线、刻度数字、指针和文字drawBg(&painter);drawDial(&painter);drawScaleNum(&painter);drawIndicator(&painter);drawText(&painter);QWidget::paintEvent(event);
}void DialPlateWidget::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 DialPlateWidget::drawDial(QPainter *painter)
{int r = radius * 0.85;double lineWidth = 1;painter->save();painter->rotate(Angle);double rotate = (double)(360 - (Angle * 2)) / 100;for (int i = 0; i <= 100; i++){QColor color = QColor(84, 84, 84);if (i <= 30)color = QColor(250, 0, 0);if (i > 30)color = QColor(0, 255, 0, 255);if ((i % 10) == 0){painter->setPen(QPen(color, 4.2 * 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 DialPlateWidget::drawScaleNum(QPainter *painter)
{painter->save();int r = (int)(radius * 0.6); // 增加半径,使刻度数字更远离中心painter->setFont(QFont("Arial", 12));painter->setPen(QPen(QColor(255, 255, 255)));QFontMetricsF fm = QFontMetricsF(painter->font());// 计算五个标值的间隔double valueRange = maxv - minv;double valueStep = valueRange / 4.0; // 四个间隔,五个标值double angleStep = (360.0 - Angle * 2) / 4.0; // 对应的角度间隔for (int i = 0; i <= 4; ++i){double value = minv + i * valueStep; // 当前标值double angle = 90 + Angle + i * angleStep; // 当前标值对应的角度float angleArc = (int(angle) % 360) * 3.14 / 180; // 转换为弧度int x = r * cos(angleArc);int y = r * sin(angleArc);QString speed = QString::number(value);int w = (int)fm.width(speed);int h = (int)fm.height();x = x - w / 2;y = y + h / 4; // 调整文本位置painter->drawText(QPointF(x, y), speed);}painter->restore();
}void DialPlateWidget::drawIndicator(QPainter *painter)
{painter->save();QPolygon pts;int r = radius * 0.6;pts.setPoints(3, -2, 0, 2, 0, 0, r);double angle = Angle + (360.0 - 2 * Angle) * (percent / 100.0);painter->rotate(angle);// 绘制指针QRadialGradient haloGradient(0, 0, 60, 0, 0); // 辐射渐变,内部填充颜色haloGradient.setColorAt(0, QColor(100, 100, 100));haloGradient.setColorAt(1, QColor(250, 50, 50)); // redpainter->setPen(QColor(250, 150, 150)); // 边框颜色painter->setBrush(haloGradient);painter->drawConvexPolygon(pts);// 绘制中心圆圈QRadialGradient radial(0, 0, 14); // 渐变radial.setColorAt(0.0, QColor(100, 100, 100));radial.setColorAt(1.0, QColor(250, 50, 50));painter->setPen(Qt::NoPen); // 填满没有边界painter->setBrush(radial);painter->drawEllipse(-7, -7, 14, 14);painter->restore();
}void DialPlateWidget::drawText(QPainter *painter)
{painter->save();painter->setFont(QFont("Arial", 8));painter->setPen(QPen(QColor(255, 255, 255)));QFontMetricsF fm = QFontMetricsF(painter->font());QString speed = title + QString::number(m_value) + unit;int w = (int)fm.width(speed);painter->drawText(QPointF(-w / 2, (int)(0.7 * radius)), speed);painter->restore();
}void DialPlateWidget::setContent(QString title, QString unit)
{this->unit = unit;this->title = title;update(); // 更新显示
}double DialPlateWidget::getMinValue() const
{return minv;
}void DialPlateWidget::setMinValue(double minValue)
{minv = minValue;
}double DialPlateWidget::getMaxValue() const
{return maxv;
}void DialPlateWidget::setMaxValue(double maxValue)
{maxv = maxValue;
}相关文章:
C++ QT 自绘表盘
文章目录 效果图代码 效果图 代码 代码没什么好说的,直接上源码.h #pragma once#include <QWidget> #include <QPainter> #include <QResizeEvent> #include <QtMath> #include <QCoreApplication>class DialPlateWidget : public …...
数据科学与数据工程:两者的区别与交集
💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…...
MAC AndroidStudio模拟器无网络
先确认PC端是正常访问网络的; 模拟器端修改Wifi设置:设置 - 网络和互联网 - WALN设置 按照上图修改; IP设置:从DHCP修改为静态,IP地址:10.0.2.16 ,网关:10.0.2.2 , DNS…...
PHP语言的多线程编程
PHP语言的多线程编程 引言 在现代Web开发中,PHP以其简洁和易用性广受欢迎。它常用于构建动态网站和应用程序。然而,PHP本身是单线程的,这意味着它在处理多个任务时可能会受到性能限制。随着互联网的发展,对高并发、高可用性和实…...
当自动包布机遇上Profinet转ModbusTCP网关,“妙啊”,工业智能“前景无限
在自动化控制技术日新月异的当下,Profinet与ModbusTCP这两种协议在工业通信领域占据着举足轻重的地位。ModbusTCP是基于以太网的串行通信协议,而Profinet则是依托工业以太网的现场总线协议。它们在数据传输速度、实时性表现以及兼容性等方面各具特色。不…...
浅析大语言模型安全和隐私保护国内外标准和政策
过去两年,大模型技术已经普及并逐步渗透到各行各业,2025年注定是大模型应用井喷式发展的一年,AI在快速发展的同时,其带来的安全风险也逐渐凸显。人工智能系统的安全性和隐私保护已经成为社会关注的重点。 附下载:600多…...
OpenCV相机标定与3D重建(54)解决透视 n 点问题(Perspective-n-Point, PnP)函数solvePnP()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 根据3D-2D点对应关系找到物体的姿态。 cv::solvePnP 是 OpenCV 库中的一个函数,用于解决透视 n 点问题(Perspective-n-Po…...
Chatper 4: Implementing a GPT model from Scratch To Generate Text
文章目录 4 Implementing a GPT model from Scratch To Generate Text4.1 Coding an LLM architecture4.2 Normalizing activations with layer normalization4.3 Implementing a feed forward network with GELU activations4.4 Adding shortcut connections4.5 Connecting at…...
spring-mvc源码分析v3.3.0
分析下springboot内嵌tomcat启动流程,即springboot-mvc <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>3.3.0</version> </dependency>环境…...
Rust实现智能助手 - 项目初始化
文章目录 前言环境准备依赖代码运行使用最后 前言 你好,我是醉墨居士,最近准备花一些时间来使用Rust语言实现一个智能助手,希望能够帮助到你。 环境准备 安装Rust语言环境,你可以从官网下载安装包安装。安装Ollama,…...
sparkSQL练习
1.前期准备 (1)建议先把这两篇文章都看一下吧,然后把这个项目也搞下来 (2)看看这个任务 (3)score.txt student_id,course_code,score 108,3-105,99 105,3-105,88 107,3-105,77 105,3-245,87 1…...
QT跨平台应用程序开发框架(2)—— 初识QT
目录 一,创建helloworld 1.1 通过图形化 1.2 通过代码 1.3 通过编辑框 1.4 使用按钮 二,对象树 2.1 关于对象树 2.2 演示释放流程 三,乱码问题 3.1 为什么会有乱码问题 3.2 解决乱码问题 四,认识Qt坐标系 五…...
[创业之路-248]:《华为流程变革:责权利梳理与流程体系建设》华为流程的前端拉动后端,与计算机软件的前端应用与后端程序的类比关系
华为的前端拉动后端模式与计算机前端应用与后端程序的类比关系,虽然两者属于不同的领域,但在某些方面存在有趣的相似性。以下是对这两者的类比关系的详细探讨: 一、华为的前端拉动后端模式 定义与特点: 华为的前端拉动后端模式是…...
汇总统计数据--SQL中聚集函数的使用
目录 1、为什么需要汇总数据 2、聚集函数 (1)AVG函数 (2)COUNT函数 (3)MAX和MIN函数 (4)SUM函数 3、聚集不同值--DISTINCT 4、组合聚集函数 5、小结 博主用的是mysql8 DBMS…...
【C盘清理】C盘清理工具、Unity缓存文件转移
链接: https://pan.baidu.com/s/1yE_7qF741o4NmBIsrd3XzA?pwdbwnn CCleaner 用于清理磁盘垃圾 勾选你要分析的选项,点击分析,分析完毕后,点击清理。 主要别清错东西了。(可以不要勾选网络缓存、网络记录相关的选项࿰…...
C# 迭代,递归,回调--13
目录 一.迭代 迭代器示例: 关键点: 优势: 二.递归 递归示例: 关键点: 优势: 注意: 三.回调 回调示例: 关键点: 优势: 应用场景: 4.三种模式的特点对比: 迭代: 递归: 回调: 一.迭代 在C#中迭代通常指重复执行一系列指令 在C#中,迭代器是一种特殊的结构,允许…...
海康大数据面试题及参考答案
请详细描述 YARN 提交程序的流程。 YARN(Yet Another Resource Negotiator)是一个资源管理系统,用于管理集群中的计算资源。以下是在 YARN 中提交程序的详细流程: 首先是客户端准备阶段。用户编写好应用程序,这个程序可以是 MapReduce、Spark 或者其他基于 YARN 的计算框架…...
软件测试 —— 自动化测试(Selenium)
软件测试 —— 自动化测试(Selenium) 什么是SeleniumPython安装Selenium1.安装webdirver-manager2.安装Selenium 写一个简单用例CSS_SELECTOR和XPATH浏览器快速定位页面元素浏览器的前进(forward),后退(bac…...
华为2024嵌入式研发面试题
01 你认为最好的排序算法是什么? 在实际的编程中,最好的排序算法要根据实际需求和数据规模来选择,因为每种排序算法都有其优势和劣势。以下是一些常见排序算法及其优缺点: 冒泡排序 冒泡排序是一种简单直观的排序算法࿰…...
centos 搭建nginx+配置域名+windows访问
准备工作:一个完整的centos环境,nginx安装包(可以从官网下载)nginx: download 一:centos可能有精简版,部分环境没有相关依赖包, 需要检查以下项: 1.gcc检查:gcc -v(回车后应当有版…...
UE5 BaseEditorSettings.ini加载原理与配置生效机制
1. 为什么你改了BaseEditorSettings.ini却没生效?——从UE5编辑器启动流程讲起很多人在UE5项目里折腾半天,把BaseEditorSettings.ini文件翻来覆去改了十几遍,重启编辑器后发现:缩放比例还是不对、网格间距没变、甚至“启用实时预览…...
Python基础语法:访问器@property和修改器@xxx.setter
一、简介 访问器和修改器也是装饰器的一种。 property: 访问器,getter xxx.setter: 修改器,setter 访问器和修改器的根本目的是想将属性私有化,提供getter&setter去访问。 访问器和修改器能够做到访问属性其实在调用getter方法࿰…...
古戏台构件声学特性的时域有限差分方法【附模型】
✨ 长期致力于时域有限差分法、窑洞、戏台、八字墙、共形技术研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方式》 (1)曲面共形网格快速生成算法: …...
UOS系统下WPS卸载不干净?手把手教你用命令行精准清理(附dpkg/apt组合拳)
UOS系统下WPS卸载不干净?手把手教你用命令行精准清理 在UOS系统日常使用中,WPS Office作为常用办公软件,有时因版本更新或功能调整需要彻底卸载。但不少用户发现,通过图形界面或简单命令卸载后,系统中仍残留配置文件、…...
组态王通用扫码枪配置
使用组态王扫码枪驱动,是绑定变量,扫码后直接就可以显示扫码内容。解决每次扫码输入数据时必须先用鼠标点进输入框内的问题。驱动安装先添加驱动,亚控网站的文件为 barcodescanner,这个文件是组态王通用扫码枪的驱动,但…...
如何让Rhino 3D模型在Blender中保持完整数据:import_3dm插件深度解析
如何让Rhino 3D模型在Blender中保持完整数据:import_3dm插件深度解析 【免费下载链接】import_3dm Blender importer script for Rhinoceros 3D files 项目地址: https://gitcode.com/gh_mirrors/im/import_3dm 当建筑师需要在Blender中渲染Rhino设计的建筑模…...
人类防伪指南:为什么你越写错字,HR越信你是真人?
前言各位码农、算法侠、CtrlC/V十级学者请注意:你有没有过这样的经历?辛辛苦苦肝了一晚上文档,逻辑严密、语法丝滑、连Markdown都对齐得像军训方阵,结果老板幽幽来一句:“这真是你自己写的?”那一刻&#x…...
2027考研全套资料免费分享
备战27考研最全备考资料整理完毕,一路走来深知备考搜集资料耗费大量时间,浪费不少精力。特意整理2027考研全科完整版资源,全部打包汇总,零基础考生直接拿来就能使用,省去四处搜集资料的烦恼。资料内含:&…...
5个必知的Universal-Updater高级功能:从QR扫描到后台安装
5个必知的Universal-Updater高级功能:从QR扫描到后台安装 【免费下载链接】Universal-Updater An easy to use app for installing and updating 3DS homebrew 项目地址: https://gitcode.com/gh_mirrors/un/Universal-Updater Universal-Updater是一款专为任…...
C++ vector容器总结
vector基本概念功能:vector数据结构和数组非常相似,也称为单端数组vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展动态扩展:并不是在原空间之后续接新空间,而是找更大的内存空间&a…...
