Qt自定义控件:汽车速度表

1、功能

制作一个汽车速度表

2、实现

从外到内进行绘制,初始化画布,画渐变色外圈,画刻度,写刻度文字,画指针,画扇形,画内圈渐变色,画黑色内圈,写当前值

3、效果

汽车速度表

4、源码
a、头文件
#ifndef CARDASHBOARD_H
#define CARDASHBOARD_H#include <QTimer>
#include <QWidget>class CarDashboard : public QWidget {Q_OBJECTpublic:CarDashboard(QWidget *parent = nullptr);~CarDashboard();protected:void paintEvent(QPaintEvent *event);private:void startSpeed();void initCanvas(QPainter &painter);void drawOutterShine(QPainter &painter);void drawScale(QPainter &painter);void drawScaleText(QPainter &painter);void drawPointer(QPainter &painter);void drawSector(QPainter &painter);void drawInnerShine(QPainter &painter);void drawInnerBlack(QPainter &painter);void drawCurrentValue(QPainter &painter);private:const int kScaleAngle = 240;   // 刻度扇形角度const int kScaleNum = 60;      // 刻度数量const int kLengthScale = 5;    // 长刻度与刻度比例const int kOneScaleValue = 4;  // 一个刻度对应值double av_angle_ = 0;               // 平均角度int start_rotate_angle_clock_ = 0;  // 起始旋转角度(顺时针)(推算出来的)int start_rotate_angle_ = 0;  // 起始旋转角度(逆时针)(推算出来的)int pointer_dir_ = 0;        // 指针旋转方向int scale_value_ = 0;        // 刻度值int height_half_ = 0;        // 高度一半int min_unit_ = 0;           // 最小单位值int font_size_ = 0;          // 字体大小int scale_text_radius_ = 0;  // 刻度文字半径int indent_value_ = 0;       // 刻度缩进值QTimer *timer_ = nullptr;  // 定时器
};
#endif  // CARDASHBOARD_H
b、源文件
#include "cardashboard.h"#include <QPainter>
#include <QtMath>CarDashboard::CarDashboard(QWidget *parent) : QWidget(parent) {av_angle_ = kScaleAngle * 1.0 / kScaleNum;start_rotate_angle_clock_ = -kScaleAngle / 2 + 270;start_rotate_angle_ = kScaleAngle / 2 + 90;startSpeed();
}CarDashboard::~CarDashboard() {}void CarDashboard::startSpeed() {timer_ = new QTimer(this);connect(timer_, &QTimer::timeout, [=]() {update();if (pointer_dir_ == 0) {scale_value_++;if (scale_value_ >= kScaleNum) {pointer_dir_ = 1;}} else if (pointer_dir_ == 1) {scale_value_--;if (scale_value_ == 0) {pointer_dir_ = 0;}}});timer_->setInterval(50);timer_->start();
}void CarDashboard::initCanvas(QPainter &painter) {painter.setRenderHint(QPainter::Antialiasing, true);// 黑色背景painter.setBrush(Qt::black);painter.drawRect(rect());painter.setBrush(Qt::NoBrush);painter.translate(QPoint(width() / 2, height() * 0.6));height_half_ = height() / 2;                            // 高度一半min_unit_ = height() / 16;                              //  最小单位值font_size_ = min_unit_ * 2 / 5;                         // 字体大小scale_text_radius_ = height_half_ - min_unit_ * 7 / 8;  // 刻度文字半径indent_value_ = min_unit_ / 8;                          // 刻度缩进大
}void CarDashboard::drawOutterShine(QPainter &painter) {const int radius = height_half_ + min_unit_ / 2;painter.save();QRect rect(-radius, -radius, radius * 2, radius * 2);QRadialGradient gradient(0, 0, radius);gradient.setColorAt(1.0, QColor(255, 0, 0, 200));gradient.setColorAt(0.97, QColor(255, 0, 0, 120));gradient.setColorAt(0.92, QColor(0, 0, 0, 0));gradient.setColorAt(0.0, QColor(0, 0, 0, 0));painter.setPen(Qt::NoPen);painter.setBrush(gradient);painter.drawPie(rect, start_rotate_angle_ * 16, -av_angle_ * kScaleNum * 16);painter.restore();
}void CarDashboard::drawScale(QPainter &painter) {painter.save();painter.setPen(QPen(Qt::white, 3));painter.rotate(start_rotate_angle_clock_);for (int i = 0; i <= kScaleNum; i++) {if (i >= 40) {painter.setPen(QPen(Qt::red, 3));}if (i % kLengthScale == 0) {  // 长刻度painter.drawLine(height_half_ - min_unit_ / 2, 0,height_half_ - indent_value_, 0);} else {  // 短刻度painter.drawLine(height_half_ - min_unit_ / 4, 0,height_half_ - indent_value_, 0);}painter.rotate(av_angle_);}painter.restore();
}// 这个函数是难点
void CarDashboard::drawScaleText(QPainter &painter) {painter.save();painter.setPen(QPen(Qt::white, 3));QFont font("Arial", font_size_);font.setBold(true);painter.setFont(font);for (int i = 0; i <= kScaleNum; i++) {if (i % kLengthScale == 0) {// 保存坐标painter.save();// 正弦 余弦int del_x = qCos(qDegreesToRadians(start_rotate_angle_ - av_angle_ * i)) *scale_text_radius_;int del_y = qSin(qDegreesToRadians(start_rotate_angle_ - av_angle_ * i)) *scale_text_radius_;// 平移坐标系painter.translate(QPoint(del_x, -del_y));// 选择坐标系painter.rotate(-kScaleAngle / 2 + av_angle_ * i);// 绘制文字painter.drawText(QRect(-min_unit_ / 2, -min_unit_ / 2, min_unit_, min_unit_),Qt::AlignCenter, QString::number(i * kOneScaleValue));// 恢复坐标painter.restore();}}painter.restore();
}void CarDashboard::drawPointer(QPainter &painter) {painter.save();painter.setPen(Qt::NoPen);painter.setBrush(Qt::white);const QPointF point[4]{QPointF(0, 0.0),QPointF(height_half_ - min_unit_ * 5 / 2, -min_unit_ / 32.0),QPointF(height_half_ - min_unit_ * 5 / 2, min_unit_ / 32.0),QPointF(0, min_unit_ / 3.0),};painter.rotate(start_rotate_angle_clock_ + av_angle_ * scale_value_);painter.drawPolygon(point, 4);painter.restore();
}void CarDashboard::drawSector(QPainter &painter) {const int radius = height_half_ + min_unit_ / 2;painter.save();painter.setPen(Qt::NoPen);painter.setBrush(QColor(255, 0, 0, 50));QRect rect(-radius, -radius, radius * 2, radius * 2);painter.drawPie(rect, start_rotate_angle_ * 16,-av_angle_ * scale_value_ * 16);painter.restore();
}void CarDashboard::drawInnerShine(QPainter &painter) {painter.setBrush(QColor(255, 0, 0, 150));painter.drawEllipse(QPoint(0, 0), min_unit_ * 2, min_unit_ * 2);
}void CarDashboard::drawInnerBlack(QPainter &painter) {painter.setBrush(Qt::black);painter.drawEllipse(QPoint(0, 0), min_unit_ * 3 / 2, min_unit_ * 3 / 2);
}void CarDashboard::drawCurrentValue(QPainter &painter) {painter.setPen(QPen(Qt::white, 3));QFont font("Arial", font_size_ * 3 / 2);font.setBold(true);painter.setFont(font);painter.drawText(QRect(-min_unit_, -min_unit_, min_unit_ * 2, min_unit_),Qt::AlignCenter,QString::number(scale_value_ * kOneScaleValue));font.setPointSize(font_size_ * 3 / 4);painter.setFont(font);painter.drawText(QRect(-min_unit_, min_unit_ / 2, min_unit_ * 2, min_unit_ / 2),Qt::AlignCenter, "Km/h");
}void CarDashboard::paintEvent(QPaintEvent *event) {Q_UNUSED(event);QPainter painter(this);// 初始化画布initCanvas(painter);// 画外圈渐变色drawOutterShine(painter);// 画刻度drawScale(painter);// 写刻度文字drawScaleText(painter);// 画指针drawPointer(painter);// 画扇形drawSector(painter);// 画内圈渐变色drawInnerShine(painter);// 画黑色内圈drawInnerBlack(painter);// 当前值drawCurrentValue(painter);
}
5、难点

这里难点使用正弦和余弦计算绘制刻度字。

对你有用就点个赞👍,以后需要用到就收藏⭐

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/812.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

语音识别:docker部署FunASR以及springboot集成funasr

内容摘选自: https://github.com/modelscope/FunASR/blob/main/runtime/docs/SDK_advanced_guide_offline_zh.md FunASR FunASR是一个基础语音识别工具包&#xff0c;提供多种功能&#xff0c;包括语音识别&#xff08;ASR&#xff09;、语音端点检测&#xff08;VAD&#xf…

鸿蒙进阶篇-模态转场

hello大家好&#xff0c;这里是鸿蒙开天组&#xff0c;今天让我们来学习鸿蒙进阶篇-模态转场 模态转场 今天来学习模态转场&#xff0c;就是页面中弹出&#xff0c;全屏&半屏的弹框&#xff1a; 就像这样&#xff0c;模态转场主要分为半模态和全屏模态&#xff0c;上面的…

RGA DEMO 下部

#加载llm模型通过ollama最好别用ollama我是没经济条件 from langchain_community.llms import Ollama llm Ollama(model"qwen1_5-4b-chat-q2_k")#pip install langchain_ollama -i https://pypi.tuna.tsinghua.edu.cn/simple #OllamaEmbeddings 要写地址本地也要写&…

Faces in Things数据集: 由麻省理工学院、微软等联合发布,探索人类视觉错觉的新里程碑

2024-09-24&#xff0c;由麻省理工学院、微软、丰田研究院、NVIDIA联合发布的 Faces in Things&#xff0c;为我们打开了研究人类视觉错觉——尤其是面部错觉&#xff08;Pareidolia&#xff09;的新篇章。专注于人类视觉系统如何在各种随机刺激中检测到类似面孔的结构&#xf…

知识见闻 - Workday公司介绍

人力资源“一哥”Workday的前世今生 01 Duffield 既然要聊Workday&#xff0c;我们首先要认识一个人。David Duffield&#xff0c;又一位企业软件服务行业的绝对大神。 大卫杜菲尔德&#xff08;David Duffield&#xff09;出生于1941年。 40岁&#xff0c;很多职场人都已经认命…

宁德时代嵌入式面试题及参考答案(万字长文)

vector 和 list 的主要区别是什么&#xff1f; 向量&#xff08;vector&#xff09;和链表&#xff08;list&#xff09;是 C 中两种常用的容器。 从底层数据结构来讲&#xff0c;vector 是基于连续的内存存储的动态数组。这使得它可以通过索引快速访问元素&#xff0c;时间复杂…

设计模式08-行为型模式1(命令模式/迭代器模式/观察者模式/Java)

五、行为型模式 **行为模式的定义&#xff1a;**行为型模式是对不同的对象之间划分职责和算法的抽象化。行为型模式定义了系统中对象之间的交互与通信&#xff0c;研究系统在运行时对象之间的相互通信与协作&#xff0c;进一步明确对象的职责&#xff0c;包括对系统中较为复杂的…

【设计模式】结构型模式(二):代理模式

结构型模式&#xff08;二&#xff09;&#xff1a;代理模式 3.代理模式&#xff08;Proxy&#xff09;3.1 主要特点3.2 组成部分3.3 示例代码3.3.1 Subject 接口3.3.2 RealSubject 实际对象3.3.3 Proxy 代理对象3.3.4 客户端代码3.3.5 运行结果 3.4 总结 3.代理模式&#xff0…

第二十八章 Vue之自定义指令

目录 一、引言 二、自定义指令的注册和使用方式 2.1. 自定义指令-全局注册使用 2.2. 自定义指令-局部注册使用 三、自定义指令完整代码 3.1. 自定义指令全局注册/使用 3.1.1. main.js 3.1.2. App.vue 3.2. 自定义指令局部注册/使用 3.2.1. main.js 3.2.2. App.vue …

Charles简单压力测试

1.接口请求次数&#xff0c;并发量&#xff0c;请求延迟时间均可配置 1.1选中需要进行测试的接口&#xff0c;鼠标右键选中【repeat advance】 2.设置并发参数 下面的图中&#xff0c;选择了1个接口&#xff0c;每次迭代中1个接口同时请求&#xff0c;迭代1000次&#xff08;…

【uniapp3】分享一个自己写的h5日历组件

简言 分享一下自己基于uniapp写的日历组件。如果不太满足你的需求&#xff0c;可以自己改造。 日历 实现分析&#xff1a; 页面显示 - 分为顶部显示和日历显示&#xff0c;我这里做了多行和单行显示两种情况&#xff0c;主要是当时看着手机的日历做的&#xff0c;手机上的…

Java设计模式(代理模式整理中ing)

一、代理模式 1、代理模式定义&#xff1a; 代理模式&#xff1a;由于某些原因要给某对象提供一个代理以控制对该对象的访问&#xff0c;这时访问对象不适合或者不能够直接引用目标对象&#xff0c;代理对象作为访问对象与目标对象之间的中介进行连接调控调用。 2、代理模式的…

Thumb 汇编指令集,Thumb 指令编码方式,编译 Thumb 汇编代码

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ Thumb指令集 ARM 指令集&#xff1a;最早在 1985 年随第一代 ARM 处理器问世。ARM 指令集一开始是 32 位固定长度的指令&#xff0c;用于各种计算任务。 Thu…

Leetcode - 周赛421

目录 一&#xff0c;3334. 数组的最大因子得分 二&#xff0c;3335. 字符串转换后的长度 I 三&#xff0c;3336. 最大公约数相等的子序列数量 四&#xff0c;3337. 字符串转换后的长度 II 一&#xff0c;3334. 数组的最大因子得分 暴力方法就不演示&#xff0c;这里介绍一个…

文件管理工具的按路径名称归类功能大公开,将大量文件批量复制或移动到指定路径,办公软件达人的秘密武器

是否还在为成堆的文件归类而苦恼&#xff1f;想要一键就能将海量文件按路径名称轻松归类&#xff0c;无论是复制还是移动&#xff1f;别急&#xff0c;今天就让文件批量改名高手软件的按路径名称归类功能来拯救你的文件管理世界&#xff01;让我们一起告别繁琐&#xff0c;迎接…

建设NFS服务器并实现文件共享

关闭防火墙和s0 systemctl stop firewalld setenforce 0 安装NFS yum install nfs-utils -y 新建共享目录并设置权限 echo "hello" > /nfs/shared/test1 chmod -Rf 777 /nfs/shared/ 配置服务端的NFS配置文件 vim /etc/exports /nfs/shared *(ro) 启动…

曹操出行借助 ApsaraMQ for Kafka Serverless 提升效率,成本节省超 20%

本文整理于 2024 年云栖大会主题演讲《云消息队列 ApsaraMQ Serverless 演进》&#xff0c;杭州优行科技有限公司消息中间件负责人王智洋分享 ApsaraMQ for Kafka Serverless 助力曹操出行实现成本优化和效率提升的实践经验。 曹操出行&#xff1a;科技驱动共享出行未来 曹操…

(转载)Tools for Learning LLVM TableGen

前提 最近在学习有关llvm的东西&#xff0c;其中TableGen占了一部分&#xff0c;所以想特意学习下TableGen相关的语法。这里找到了LLVM官网的一篇介绍TableGen的博客&#xff0c;学习并使用机器翻译为中文。在文章的最后也添加了一些学习TableGen的资源。 原文地址&#xff1…

vue3uniapp实现自定义拱形底部导航栏,解决首次闪烁问题

前言&#xff1a; 我最初在网上翻阅查找了很多方法&#xff0c;发现大家都是说在page.json中tabbar中添加&#xff1a;"custom": true,即可解决首次闪烁的问题&#xff0c;可是添加了我这边还是会闪烁&#xff0c;因此我这边改变了思路&#xff0c;使用了虚拟页面来解…

【P2-5】ESP8266 WIFI模块在AP模式下作为TCP服务器与多个电脑/手机网络助手(TCP客户端)通信——TCP数据透传

前言:完成ESP8266 WIFI模块在AP模式下作为TCP服务器与多个电脑/手机网络助手(TCP客户端)通信——实现TCP数据透传 AP模式,通俗来说模块可以发出一个WIFI热点提供给电脑/手机连接。 TCP服务端,通俗来说就是模块/单片机作为服务器,可以接收多个客户通道的连接。 本…