QT 实现两款自定义的温度计/湿度控件
文章目录
- 0 引入
- 1、带有标尺的温度/湿度计控件
- 1.头文件
- 2.核心代码
- 2、竖起来的温度/湿度计控件
- 1.头文件
- 2.实现
- 3、引用

0 引入
QT原生控件没有实现如仪表盘或者温度计的控件,只好自己实现,文章代码部分参考引用的文章。直接上图
图一 带有标尺的温度计、湿度
图二 温度计、湿度

控件最核心的部分:在函数paintEvent绘制部分,如果需要动画效果还需要加一个QPropertyAnimation ,这是最主要的,剩下的细节根据需求增加减少即可。
1、带有标尺的温度/湿度计控件
因为只做数据显示用,所以只需要向控件传数据即可。
主要功能:1、可设置显示范围;
2、显示过程中加了动画效果;
3、背景色和前景色以及刻度尺颜色可变;
4、刻度尺间距可变,控件大小随着QWidget适应;
1.头文件
代码如下(示例):
protected:void paintEvent(QPaintEvent *);void drawBg(QPainter *painter);void drawProgress(QPainter *painter);void drawRulerTop(QPainter *painter);void drawRulerBottom(QPainter *painter);private:QPropertyAnimation *m_valueAnimation;double minValue; //最小值double maxValue; //最大值qreal value; //当前值int longStep; //长线条等分步长int shortStep; //短线条等分步长bool rulerTop; //刻度线在上面bool isAdd; //是否为增加,默认为的增加QColor bgColor; //背景颜色QColor lineColor; //线条颜色QColor progressColor; //进度颜色public:qreal getValue() const;void setrulerTop(bool istop); //设定刻度线再上还是在下,默认是在上void setValue(qreal v);void setRange(int minValue, int maxValue);void startAnimation();void updateValue(double value);void setBgColor(const QColor &bgColor); //设置背景颜色void setLineColor(const QColor &lineColor); //设置线条颜色void setProgressColor(const QColor &progressColor); //设置进度颜色
2.核心代码
绘制部分参考引用2代码,感谢刘典武老师的无私开源,有需要的可去做定制。
代码如下:
void HumidityProgress::startAnimation()
{qreal startValue = value;if(isAdd){m_valueAnimation->setKeyValueAt(0.5, value+0.5);m_valueAnimation->setKeyValueAt(1, value);m_valueAnimation->setStartValue(startValue-0.5);m_valueAnimation->start();}else{m_valueAnimation->setKeyValueAt(0.5, value-0.5);m_valueAnimation->setKeyValueAt(1, value);m_valueAnimation->setStartValue(startValue+0.5);m_valueAnimation->start();}}void HumidityProgress::paintEvent(QPaintEvent *)
{//绘制准备工作,启用反锯齿QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);//按照绘制顺序drawBg(&painter);drawProgress(&painter);if (rulerTop) {drawRulerTop(&painter);} else {drawRulerBottom(&painter);}
}void HumidityProgress::drawBg(QPainter *painter)
{painter->save();painter->setPen(lineColor);painter->setBrush(bgColor);painter->drawRect(rect());painter->restore();
}void HumidityProgress::drawProgress(QPainter *painter)
{painter->save();painter->setPen(Qt::NoPen);painter->setBrush(progressColor);double length = width();double increment = length / (maxValue - minValue);double initX = (value - minValue) * increment;QRect rect(0, 0, initX, height());painter->drawRect(rect);painter->restore();
}void HumidityProgress::drawRulerTop(QPainter *painter)
{painter->save();painter->setPen(lineColor);double initX = 0;//绘制横向标尺上部分底部线double initTopY = 0;QPointF lineTopLeftPot = QPointF(initX, initTopY);QPointF lineTopRightPot = QPointF(width() - initX, initTopY);painter->drawLine(lineTopLeftPot, lineTopRightPot);//绘制上部分及下部分横向标尺刻度double length = width();//计算每一格移动多少double increment = length / (maxValue - minValue);//长线条短线条长度int longLineLen = 15;int shortLineLen = 10;//根据范围值绘制刻度值及刻度值 长线条需要移动10像素 短线条需要移动5像素for (int i = minValue; i <= maxValue; i = i + shortStep) {if (i % longStep == 0) {QPointF topPot = QPointF(initX, initTopY);QPointF bottomPot = QPointF(initX, initTopY + longLineLen);painter->drawLine(topPot, bottomPot);//第一个值和最后一个值不要绘制if (i == minValue || i == maxValue) {initX += increment * shortStep;continue;}QString strValue = QString("%1").arg((double)i, 0, 'f', 0);double textWidth = fontMetrics().width(strValue);double textHeight = fontMetrics().height();QPointF textPot = QPointF(initX - textWidth / 2, initTopY + textHeight + longLineLen);painter->drawText(textPot, strValue);} else {if (i % (longStep / 2) == 0) {shortLineLen = 10;} else {shortLineLen = 6;}QPointF topPot = QPointF(initX, initTopY);QPointF bottomPot = QPointF(initX, initTopY + shortLineLen);painter->drawLine(topPot, bottomPot);}initX += increment * shortStep;}painter->restore();
}
该处使用的url网络请求的数据。
2、竖起来的温度/湿度计控件
因为只做数据显示用,所以只需要向控件传数据即可。
控件是好看,但是大小不能改变,所以这里需要自己实现了,源码作者已经放上。
1.头文件
代码如下(示例):
#ifndef THERMOMETREDLG_H
#define THERMOMETREDLG_H#include <QWidget>
#include <QPropertyAnimation>
#include <QPainter>
#include <QTimer>class thermometreDlg : public QWidget
{Q_OBJECTQ_PROPERTY(qreal value READ getValue WRITE setValue) //声明属性public:explicit thermometreDlg(QWidget *parent = nullptr);qreal getValue();void setValue(qreal value);void changeValue(qreal value);protected:void paintEvent(QPaintEvent *e);public slots:void startAnimation();signals:private:qreal m_value;qreal curValue;int m_width;QRectF m_rect;int maxValue, minValue;qreal m_radius;QPropertyAnimation *m_valueAnimation;void updateRect();};#endif // THERMOMETREDLG_H
2.实现
代码如下(示例):
#include "thermometredlg.h"
#include <QDebug>thermometreDlg::thermometreDlg(QWidget *parent) : QWidget(parent)
{m_width = 20;maxValue = 100;minValue = 0;m_radius = 1.05;m_value = 0;curValue = m_value;QTimer *at = new QTimer(this);at->start(1000);m_valueAnimation = new QPropertyAnimation(this, "value");m_valueAnimation->setDuration(1000);m_valueAnimation->setEasingCurve(QEasingCurve::OutCubic);m_valueAnimation->setLoopCount(1);connect(at, SIGNAL(timeout()), this, SLOT(startAnimation()));}void thermometreDlg::updateRect()
{m_rect.setX(0);m_rect.setY(20 - height()/2);m_rect.setWidth(m_width);m_rect.setHeight(height() - 40 - m_width* m_radius);
}void thermometreDlg::setValue(qreal value)
{m_value = value;update();
}void thermometreDlg::changeValue(qreal value)
{if(value > maxValue)value = maxValue;if(value < minValue)value = minValue;curValue = value;
}qreal thermometreDlg::getValue()
{return m_value;
}void thermometreDlg::paintEvent(QPaintEvent *e)
{updateRect();QPainter painter(this);QPen pen(Qt::black);painter.translate(this->width()/2, this->height()/2); //坐标轴移动到中心点painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing); // 启用反锯齿painter.save();//绘制上方的柱状painter.fillRect(m_rect, QColor(168,200, 225));//绘制底部的圆QRectF tmpRect = QRectF(m_rect.bottomLeft(), QPointF(m_width, height()/2- m_width*m_radius));painter.fillRect(tmpRect, QColor(255, 0, 0));painter.setPen(Qt::NoPen);painter.setBrush(QColor(255, 0, 0));painter.drawEllipse(tmpRect.bottomLeft()+QPointF(tmpRect.width()/2, 0),m_width*m_radius, m_width*m_radius);painter.restore();//绘制刻度以及刻度值painter.save();painter.setPen(QColor(Qt::black));int nYCount = (maxValue - minValue)/10+1;qreal perHeight = (m_rect.height())/nYCount;for (int i=0; i<nYCount; ++i) {QPointF basePoint = m_rect.bottomLeft() - QPointF(0, perHeight/2) - QPointF(0, perHeight*i);//左侧大刻度painter.drawLine(basePoint, basePoint+QPointF(-10, 0));for (int j=1; j<10; ++j) {if(i == nYCount -1)continue;painter.drawLine(basePoint-QPointF(0, perHeight/10*j),basePoint-QPointF(5, perHeight/10*j));}painter.drawText(basePoint+QPointF(-28, 4), QString("%1").arg(minValue+i*10));//右侧大刻度basePoint = m_rect.bottomRight() - QPointF(0, perHeight/2) - QPointF(0, perHeight*i);painter.drawLine(basePoint, basePoint+QPointF(10, 0));for (int j=1; j<10; ++j) {if(i == nYCount -1)continue;painter.drawLine(basePoint-QPointF(0, perHeight/10*j),basePoint-QPointF(-5, perHeight/10*j));}}painter.restore();//根据值填充m_rectqreal h = (m_value-minValue)/(maxValue-minValue)*(m_rect.height()-perHeight);if(h<0)h = 0;if(h > m_rect.height())h = m_rect.height();painter.fillRect(m_rect.adjusted(0, m_rect.height()-h-perHeight/2-1 , 0, 0), QColor(255, 0, 0));QWidget::paintEvent(e);
}void thermometreDlg::startAnimation()
{qreal startValue = getValue();m_valueAnimation->setKeyValueAt(0, startValue-1);m_valueAnimation->setKeyValueAt(0.5, curValue+1);m_valueAnimation->setKeyValueAt(1, curValue);m_valueAnimation->setStartValue(startValue-2);m_valueAnimation->start();
}
3、引用
1、用qt实现一个温度计控件
2、Qt编写自定义控件2-进度条标尺
3、Qt动画框架:QPropertyAnimation(属性动画)
相关文章:
QT 实现两款自定义的温度计/湿度控件
文章目录 0 引入1、带有标尺的温度/湿度计控件1.头文件2.核心代码 2、竖起来的温度/湿度计控件1.头文件2.实现 3、引用 0 引入 QT原生控件没有实现如仪表盘或者温度计的控件,只好自己实现,文章代码部分参考引用的文章。直接上图 图一 带有标尺的温度计…...
Fourier分析导论——第4章——Fourier级数的一些应用(E.M. Stein R. Shakarchi)
第 4 章 傅里叶级数的一些应用 Fourier series and analogous expansions intervene very naturally in the general theory of curves and surfaces. In effect, this theory, conceived from the point of view of analysis, deals obviously with the study of arbitra…...
c语言使用fdk_aac库对aac音频解码为pcm
//示例为adts的aac流数据(adts数据可以每一包都可以独立解析不需要拼凑) //解码数据的采样率同解码前的采样率,如果不满足需求,需要对数据进行重采样 #include <aacdecoder_lib.h>int m_fd -1; int m_fd2 -1;void aac2pc…...
zustand管理工具--React
npm i zustand 1.函数参数必须返回一个对象 对象内部编写状态数据和方法 2.set是用来修改数据的专门方法必须调用它来修改数据 import { useEffect } from "react"; import { create } from "zustand";// 1. 创建store const goodsStore create((set) …...
Elasticsearch内存分析
文章目录 Elasticsearch JVM内存由哪些部分组成Indexing BufferNode Query CacheShard Request CacheField Data CacheSegments Cache查询 非堆内存内存压力mat分析es的jvm缓存监控 Elasticsearch JVM内存由哪些部分组成 官方建议Elasticsearch设置堆内存为32G,因为…...
Alert警告提示(antd-design组件库)简单使用
1.Alert警告提示 警告提示,展现需要关注的信息。 2.何时使用 当某个页面需要向用户显示警告的信息时。 非浮层的静态展现形式,始终展现,不会自动消失,用户可以点击关闭。 组件代码来自: 警告提示 Alert - Ant Design 3…...
Linux提权方法总结
1、内核漏洞提权 利用内核漏洞提取一般三个环节:首先对目标系统进行信息收集,获取系统内核信息及版本信息 第二步,根据内核版本获取对应的漏洞以及exp 第三步,使用exp对目标进行攻击,完成提权 注:此处可…...
力扣第300题 最长递增子序列 c++ 动态规划题 附Java代码
题目 300. 最长递增子序列 中等 相关标签 数组 二分查找 动态规划 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例…...
Si3262 集成低功耗SOC 三合一智能门锁应用芯片
Si3262 是一款G度集成的低功耗 SOC 芯片,其集成了基于 RISC-V 核的低功耗MCU 和工作在 13.56MHz 的非接触式读写器模块。 读写器模块支持 ISO/IEC 14443 A/B/MIFARE 协议,支持自动载波侦测功能(ACD)。无需外W其他电路,…...
linux rsyslog介绍
Rsyslog网址:https://www.rsyslog.com/ Rsyslog is the rocket-fast system for log processing. It offers high-performance, great security features and a modular design. While it started as a regular syslogd, rsyslog has evolved into a kind of swis…...
项目部署之安装和配置Canal
1.Canal介绍 Canal是阿里巴巴的一个开源项目,基于java实现,整体已经在很多大型的互联网项目生产环境中使用,包括阿里、美团等都有广泛的应用,是一个非常成熟的数据库同步方案,基础的使用只需要进行简单的配置即可。 …...
基于Skywalking的全链路跟踪实现
在前文“分布式应用全链路跟踪实现”中介绍了分布式应用全链路跟踪的几种实现方法,本文将重点介绍基于Skywalking的全链路实现,包括Skywalking的整体架构和基本概念原理、Skywalking环境部署、SpringBoot和Python集成Skywalking监控实现等。 1、Skywalki…...
Spark Core
Spark Core 本文来自 B站 黑马程序员 - Spark教程 :原地址 第一章 RDD详解 1.1 为什么需要RDD 分布式计算需要 分区控制shuffle控制数据存储、序列化、发送数据计算API等一系列功能 这些功能,不能简单的通过Python内置的本地集合对象(如…...
[算法日志]图论: 广度优先搜索(BFS)
[算法日志]图论: 广度优先搜索(BFS) 广度优先概论 广度优先遍历也是一种常用的遍历图的算法策略,其思想是将本节点相关联的节点都遍历一遍后才切换到相关联节点重复本操作。这种遍历方式类似于对二叉树节点的层序遍历,即先遍历完子节点后…...
Xilinx FPGA SPIx4 配置速度50M约束语句(Vivado开发环境)
qspi_50m.xdc文件: set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design] set_property CONFIG_VOLTAGE 3.3 [curren…...
Linux Shell和权限
目录 Shell命令及运行原理 权限 1.文件基本属性 2.文件权限值的表示方法 3.文件访问权限的相关设置方法 3.(1)chmod 组名修改 3.(2)chmod 二进制修改 3.(3)chown 3.(4)chgrp 3.(5)umask 4.目录权限 Shell命令及运行原理 Linux的操作系统,狭义上是…...
Git同时配置Gitee和GitHub
Git同时配置Gitee和GitHub 一、删除原先ssh密钥二、生成密钥 这里的同时配置是针对于之前配置过单个gitee或者github而言的,如果需要看git从安装开始的配置,则可以看这一篇文章 git安装配置教程 一、删除原先ssh密钥 在C盘下用户/用户名/.ssh文件下找到…...
IGP高级特性简要介绍(OSPF-上篇)
OSPF高级特性 一、OSPF_提升故障收敛及网络恢复速度 1.FRR与BFD快速恢复故障 1.1 FRR 在传统转发模式下,当到达同一个目的网络存在多条路由时,路由器总是选择最优路由使用,并且下发到FIB表指导数据转发。 当最优路由故障时,需…...
Oracle-Ogg集成模式降级为经典模式步骤
前言: Ogg集成模式降级为经典模式的场景比较少,因为降级为经典模式会导致无法支持压缩表同步,XA事务,多线程模式,PDB模式同步等功能,除非遇到集成模式暂时无法解决的bug或者环境不支持集成模式,比如DG备库环…...
链表面试OJ题(1)
今天讲解两道链表OJ题目。 1.链表的中间节点 给你单链表的头结点 head ,请你找出并返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。 示例 输入:head [1,2,3,4,5] 输出:[3,4,5] 解释:链表只有一个…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
