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] 解释:链表只有一个…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...

算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...

leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...