动态时钟控件:Qt/C++ 项目代码解读

news2024/11/19 14:34:12

基于Qt的动态时钟控件项目。该项目展示了如何通过Qt的绘图系统绘制一个带有表盘背景、时针、分针、秒针、以及时间日期显示的时钟。同时,这个时钟控件支持背景切换,并且每秒钟刷新一次,实时显示当前时间。

项目结构与功能概述

该时钟控件主要通过 QPainterQWidget 上绘制,利用 QTimer 来定时更新显示内容,使得时针、分针和秒针随时间转动。此外,还展示了如何通过绘制多边形来生成不同的指针,以及如何将表盘背景和数字刻度正确地绘制到窗口上。
在这里插入图片描述

代码部分解读

下面是代码的详细解读,按功能逐步解释。

# include "ClockWidget.h"
# include <QPainter>
# include <QTimer>
# include <QtMath>
# include <QDebug>

首先,项目包括了必要的Qt模块:

  • QPainter:负责处理绘图的核心类。
  • QTimer:用于每秒更新时钟控件。
  • QtMath:提供数学函数,特别是角度到弧度的转换。
  • QDebug:用于调试。
构造函数和定时器
ClockWidget::ClockWidget(QWidget *parent) : QWidget(parent) {
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, [=](){this->update();});
    timer->start(1000); // 更新频率为1秒
    m_background = QPixmap("clock_face.png"); // 从资源加载表盘背景图像
}
  1. QTimer:每秒触发一次 timeout 信号,连接到控件的 update() 函数,从而刷新时钟界面,实现动态更新。
  2. m_background:使用 QPixmap 加载一个图像作为表盘背景。
paintEvent() 函数:绘制时钟界面
void ClockWidget::paintEvent(QPaintEvent *event) {
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.translate(width() / 2, height() / 2); // 将坐标原点移到中心

    int side = qMin(width(), height());
    QPixmap scaledBg = m_background.scaled(side, side, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    painter.drawPixmap(-side / 2, -side / 2, scaledBg);

    int radius = side / 2;
    drawHands(painter, radius);
    drawNumerals(painter, radius);
    drawClockFace(painter, radius);
}

paintEvent() 中,通过 QPainter 实现整个时钟界面的绘制。

  1. setRenderHint(QPainter::Antialiasing):开启抗锯齿,使绘图更平滑。
  2. translate(width() / 2, height() / 2):将原点平移到窗口的中心,便于以中心为参考绘制时钟。
  3. 背景图像缩放:使用 scaled() 将表盘背景缩放到合适大小,并使用平滑变换。

接下来,调用了三个函数:

  • drawHands():绘制时针、分针和秒针。
  • drawNumerals():绘制时钟上的数字刻度。
  • drawClockFace():绘制表盘刻度。
drawClockFace() 函数:绘制时钟刻度
void ClockWidget::drawClockFace(QPainter &painter, int radius) {
    painter.setPen(QPen(Qt::white, 2)); // 设置刻度颜色和粗细

    // 绘制小时刻度
    for (int i = 0; i < 12; ++i) {
        painter.drawLine(0, -radius, 0, -radius + radius * 0.1);
        painter.rotate(30.0); // 30度一个小时
    }

    // 绘制分钟刻度
    painter.setPen(QPen(Qt::white, 1)); // 分钟刻度更细
    for (int j = 0; j < 60; ++j) {
        if (j % 5 != 0) { // 避免与小时刻度重叠
            painter.drawLine(0, -radius, 0, -radius + radius * 0.05);
        }
        painter.rotate(6.0); // 6度一分钟
    }
}
  1. 绘制小时刻度:使用 rotate() 每次旋转 30 度,绘制 12 个小时刻度。
  2. 绘制分钟刻度:与小时刻度类似,分钟刻度每次旋转 6 度,但线条更短、更细,避免与小时刻度重叠。
drawHands() 函数:绘制时针、分针和秒针
void ClockWidget::drawHands(QPainter &painter, int radius) {
    QTime time = QTime::currentTime();

    // 绘制时针
    painter.save();
    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::darkGray);
    int hour = time.hour() % 12;
    double minute = time.minute();
    double hourAngle = (hour * 30.0) + (minute * 0.5); // 时针角度
    painter.rotate(hourAngle); 
    painter.drawConvexPolygon(QPolygon() << QPoint(-radius * 0.05, 0)
                              << QPoint(0, -radius * 0.5)
                              << QPoint(radius * 0.05, 0)
                              << QPoint(0, radius * 0.05));
    painter.restore();
    
    // 分针与秒针类似
}
  1. 绘制时针:时针的角度根据当前小时和分钟计算出来,通过 rotate() 旋转相应的角度后绘制时针形状。
  2. 分针和秒针:与时针类似,但角度基于分钟和秒钟进行计算,并使用不同的形状和颜色。
drawNumerals() 函数:绘制时钟上的数字
void ClockWidget::drawNumerals(QPainter &painter, int radius) {
    QString numbers[] = {"12", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11"};
    painter.setPen(Qt::white);
    painter.setFont(QFont("Arial", radius / 15));

    for (int i = 0; i < 12; ++i)
    {
        double angle = 30 * i - 92 ; 
        double radian = qDegreesToRadians(angle);
        int x = radius * 0.8 * qCos(radian);
        int y = radius * 0.8 * qSin(radian);
        painter.drawText(x - 10, y - 20, 20 + radius / 15, 20 + radius / 15, Qt::AlignCenter, numbers[i]);
    }

    // 显示日期和时间
    QDateTime currentTime = QDateTime::currentDateTime();
    painter.setFont(QFont("Arial", radius / 20));
    painter.drawText(-radius / 2, radius / 2 - 40, radius, 20 + radius / 15, Qt::AlignCenter, currentTime.toString("yyyy-MM-dd HH:mm:ss"));
}
  1. 绘制数字刻度:将数字 12-11 绘制到表盘上,利用三角函数将数字定位在合适的位置。
  2. 日期时间显示:在表盘中心下方显示当前的日期和时间。

总结

这个项目展示了如何在 Qt 中利用 QPainter 实现一个动态的时钟控件,并且实现了时钟背景的自定义功能。通过结合 QTimer 来定时更新界面,实现了秒针、分针、时针的动态变化。

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

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

相关文章

Redis接口访问优化

说明&#xff1a;之前写过一篇使用Redis接口访问的博客&#xff0c;如下。最近有相关需求&#xff0c;把代码拿出来后&#xff0c;做了一些优化&#xff0c;挺有意思的&#xff0c;本文介绍在原基础上 使用Redis实现接口防抖 优化 总的来说&#xff0c;这次使用Redis实现接口…

自动驾驶汽车横向控制方法研究综述

【摘要】 为实现精确、稳定的横向控制&#xff0c;提高车辆自主行驶的安全性和保障乘坐舒适性&#xff0c;综述了近年来自动驾驶汽车横向控制方法的最新进展&#xff0c;包括经典控制方法和基于深度学习的方法&#xff0c;讨论了各类方法的性能特点及在应用中的优缺点&#xff…

【初阶数据结构】详解插入排序 希尔排序(内含排序的概念和意义)

文章目录 前言1. 排序的概念及其应用1.1 排序的概念1.2 排序的应用 2. 插入排序2.1 基本思想2.2 插入排序的代码实现2.3 插入排序算法总结 3. 希尔排序3.1 基本思想3.2 希尔排序的代码实现3.3 希尔排序的特征总结 前言 初级数据结构系列已经进入到了排序的部分了。相信大家听到…

计算机毕业设计 服装生产信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

记录|Modbus-TCP产品使用记录【德克威尔】

目录 前言一、德克威尔1.1 实验图1.2 DECOWELL IO Tester 软件1.3 读写设置1.4 C#进行Modbus-TCP读写 更新时间 前言 参考文章&#xff1a; 使用的第二款Modbus-TCP产品。 一、德克威尔 1.1 实验图 1.2 DECOWELL IO Tester 软件 这也是自带模块配置软件的。下图就是德克威尔的…

“Xian”(籼)和“Geng”(粳)米怎么读?

2018年&#xff0c;《自然》上刊登了一篇有关亚洲栽培稻基因组变异的重磅论文。研究成果本身自然引人关注&#xff0c;但更引人关注的是&#xff0c;这篇论文首次提出以“Xian”&#xff08;籼&#xff09;和“Geng”&#xff08;粳&#xff09;两个汉语农业术语代替Indica和Ja…

yum使用阿里云的镜像源报错 Failed connect to mirrors.aliyuncs.com:80; Connection refused“

报错&#xff1a;Failed connect to mirrors.aliyuncs.com:80; Connection refused"&#xff0c;如果单独只是这个报错的话&#xff0c;那么原因是由于非阿里云ECS用户无法解析主机“mirrors.cloud.aliyuncs.com”。如果不单单只是这个报错另外还有其它报错请参考我其它文…

Threejs创建正多边体

上一章节实现了球体的绘制&#xff0c;这节来绘制多面体&#xff0c;包括正多面体&#xff0c;平面中&#xff0c;每条边一样长组成的图形叫正多边形&#xff0c;这里每个面一样&#xff0c;叫正多面体。如上文一样&#xff0c;先要创建出基础的组件&#xff0c;包括场景&#…

C++基础---类和对象(上)

1.类的定义 C程序设计允许程序员使用类&#xff08;class&#xff09;定义特定程序中的数据类型。这些数据类型的实例被称为对象 &#xff0c;这些实例可以包含程序员定义的成员变量、常量、成员函数&#xff0c;以及重载的运算符。语法上&#xff0c;类似C中结构体&#xff0…

【机器学习】任务六:分类算法(支持向量机(SVM)在线性可分与不可分数据中的应用与可视化分析)

目录 1.知识简介 2.SVM 支持向量机模型训练与可视化报告 2.1 导入本项目所需的模块和包 &#xff08;1&#xff09;目的 &#xff08;2&#xff09;代码实现 &#xff08;3&#xff09;代码解释 2.2 随机生成线性可分的数据并可视化 &#xff08;1&#xff09;目的 &a…

[数据集][目标检测]电力场景防震锤缺陷检测数据集VOC+YOLO格式705张1类别

重要说明&#xff1a;防震锤缺陷图片太难找&#xff0c;数据集里面存在大量单一场景图片&#xff0c;请仔细查看图片预览谨慎下载&#xff0c;此外数据集均为小目标检测&#xff0c;如果训练map偏低属于正常现象 数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径…

特殊的 BASE64 1

这个一看题目就是base64编码表被改了. 知识点&#xff1a; Base64编码使用一个包含64个字符的字符集&#xff0c;这些字符分别是&#xff1a; 大写字母A-Z小写字母a-z数字0-9特殊字符和/ 这些字符分别对应64个不同的6位二进制数。在补零后形成的8位字节中&#xff0c;实际使用…

c++primier第十二章类和动态内存

本章内容包括&#xff1a; 对类成员使用动态内存分配隐式和显式地复制构造函数隐式和显式地重载赋值操作符在构造函数中使用new所必须完成的工作使用静态类成员 将布局new操作符用于对象使用指向对象的指针实现队列抽象数据类型(ADT) 动态内存和类 复习范例和静态类成员 首…

ASP.NET Zero 多租户介绍

ASP.NET Zero 是一个基于 ASP.NET Core 的应用程序框架&#xff0c;它提供了多租户支持&#xff0c;以下是关于 ASP.NET Zero 多租户的介绍&#xff1a; 一、多租户概念 多租户是一种软件架构模式&#xff0c;允许多个客户&#xff08;租户&#xff09;共享同一套软件应用程序…

联邦学习(三只决策和大数据分析)(学习笔记)

联邦学习模型按照数据重叠形式分成了三类&#xff0c;分别是横向联邦学习、纵向联邦学习和联邦迁移学习。 横向联邦学习模型针对特征一致但ID不一致的数据&#xff1b; 纵向联邦学习模型针对ID一致但特征不一致的数据&#xff1b; 联邦迁移学习模型针对ID和特征都不一致的数据。…

Linux网络操作命令与函数全面总结

1. 引言 Linux作为服务器和开发平台&#xff0c;网络操作是其核心功能之一。本文旨在全面总结Linux系统中的网络操作方法&#xff0c;包括命令行工具和编程接口&#xff0c;帮助读者深入理解Linux网络管理的机制。 2. 命令行工具 2.1 ping 命令 ping 命令用于测试网络连接和…

实验OSPF路由协议(课内实验)

实验1&#xff1a;OSPF路由协议 实验目的及要求&#xff1a; 通过实验&#xff0c;能够理解链路状态型路由协议OSPF协议的工作原理&#xff0c;掌握如何实现单区域 OSPFv2配置指令&#xff0c;能够熟练的应用各种OSPF协议相关的配置指令完善网络设计。掌握验证OSPFv2网络连接…

软件开发人员绩效考核方案(参考)

1、产品&运营绩效考核表 2、开发绩效考核表 3、测试绩效考核表 4、CPI指标库 软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查…

像AI一样思考

我感觉每个人都应该通过Coze平台 https://www.coze.cn/ 创建一个属于自己的Bot。 为什么要创建Bot&#xff1f; 很多时候我们的思维会受各种因素的影响&#xff0c;如感情、知识盲区、心态等&#xff0c;最终导致我们做的决定缺乏逻辑或者考虑不全面。但AI不一样&#xff0c;…

armbian安装docker

最近又搞了台瑞莎Radxa 3E &#xff0c;从零开始部署unbuntu环境&#xff0c;发现是真曲折啊&#xff0c;虽然有点前车之鉴了 在Armbian上安装Docker&#xff0c;可以按照以下步骤操作&#xff1a; 1、更新软件包列表&#xff1a; sudo apt-get update 2、安装必要的软件包…