当前位置: 首页 > news >正文

QT修仙笔记 事件大圆满 闹钟大成

学习笔记
牛客刷题

闹钟

在这里插入图片描述

  1. 时钟显示 通过 QTimer 每秒更新一次 QLCDNumber 显示的当前时间,格式为 hh:mm:ss,实现实时时钟显示。

  2. 闹钟设置

  • 使用 QDateTimeEdit 让用户设置闹钟时间,可通过日历选择日期,设置范围为当前时间到未来 10 天。
  1. 提醒功能
  • 语音播报:当到达设定的闹钟时间,从 QPlainTextEdit 获取文本,利用 QTextToSpeech 进行语音播报。
  • 音效播放:同时,使用 QMediaPlayer 播放指定的提醒音效文件 123.mp3,音量设为 80。
  1. 控制操作
  • 启动闹钟:点击“启动”按钮,开启定时器进行时间检查,此时“启动”按钮禁用,“停止”按钮启用。
  • 停止闹钟:点击“停止”按钮,停止定时器和音效播放,“启动”按钮重新启用,“停止”按钮禁用。
#include "widget.h"
#include "ui_widget.h"
#include<QTime>
#include<QDateTime>
#include<QTextToSpeech>
#include<QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//创建时钟timerTime=new QTimer(this);timerClock=new QTimer(this);//绑定时钟函数connect(timerTime,&QTimer::timeout,this,&Widget::timeSlot);connect(timerClock,&QTimer::timeout,this,&Widget::clockSlot);//时钟直接启动timerTime->start(1000);ui->timeLCD->setDigitCount(8);ui->dateTimeEdit->setCalendarPopup(true);ui->dateTimeEdit->setMinimumDateTime(QDateTime::currentDateTime());ui->dateTimeEdit->setMaximumDate(QDate::currentDate().addDays(10));ui->dateTimeEdit->setDisplayFormat("yyyy-MM-dd hh:mm:ss");speech=new QTextToSpeech(this);startSound=new QMediaPlayer(this);startSound->setMedia(QUrl("qrc:/new/prefix1/123.mp3"));startSound->setVolume(80);  //音量}Widget::~Widget()
{delete ui;
}void Widget::on_startBtn_clicked()
{//计时器启动this->timerClock->start(1000);ui->startBtn->setEnabled(false);ui->endBtn->setEnabled(true);}void Widget::on_endBtn_clicked()
{
// 取消this->timerClock->stop();startSound->stop();ui->startBtn->setEnabled(true);ui->endBtn->setEnabled(false);
}
//时钟增加函数
void Widget::timeSlot()
{QTime time;ui->timeLCD->display(time.currentTime().toString("hh:mm:ss"));
}
//闹钟函数
void Widget::clockSlot()
{QDateTime dt=ui->dateTimeEdit->dateTime();//    QDateTime now;if(dt.secsTo(QDateTime::currentDateTime())==0){//播报QString text=ui->plainTextEdit->toPlainText();speech->say(text);ui->startBtn->setEnabled(true);timerClock->stop();startSound->play();}
}

学习笔记

一、QObject::event

  1. 函数名bool QObject::event(QEvent *e)
  2. 函数功能:这是Qt事件处理的入口函数。当一个事件发生时,首先会调用该函数。它会根据传入的事件对象e,识别事件类型,然后进行初步处理或分发到更具体的事件处理函数。比如,它可以判断事件是鼠标事件、键盘事件还是其他类型事件,进而决定后续处理流程。
  3. 函数参数QEvent *e,这是一个指向QEvent对象的指针。QEvent是所有事件类的基类,通过它可以获取事件的详细信息,如事件类型、发生时间等。
  4. 函数返回值bool类型。如果事件被成功处理,返回true;若未处理或需要进一步处理,则返回false。返回值会影响事件的后续传递,如果返回false,事件可能会继续向上传递给父对象处理。
  5. 主要函数举例
class MyObject : public QObject {Q_OBJECT
public:bool event(QEvent *e) override {if (e->type() == QEvent::MouseButtonPress) {qDebug() << "Mouse button pressed event caught in event()";return true;}return QObject::event(e);}
};

在这个例子中,MyObject类继承自QObject并重写了event函数。当检测到鼠标按下事件时,输出相应信息并返回true,表示事件已处理;否则,调用父类的event函数继续处理事件。

二、QWidget的鼠标事件处理函数

(一)mousePressEvent

  1. 函数名void QWidget::mousePressEvent(QMouseEvent *event)
  2. 函数功能:当鼠标按键在部件上按下时被调用。常用于记录鼠标按下的位置,为后续的绘图、拖曳等操作做准备。
  3. 函数参数QMouseEvent *event,通过它可以获取鼠标事件的详细信息,包括按下的是哪个鼠标按键(如Qt::LeftButtonQt::RightButton等),鼠标在部件上的位置(相对于部件的坐标pos())以及在屏幕上的全局坐标(globalPos())等。
  4. 函数返回值void,没有返回值,专注于处理鼠标按下事件的相关逻辑。
  5. 主要函数举例
class MyWidget : public QWidget {Q_OBJECT
public:void mousePressEvent(QMouseEvent *event) override {if (event->button() == Qt::LeftButton) {qDebug() << "Left mouse button pressed at local position:" << event->pos();} else if (event->button() == Qt::RightButton) {qDebug() << "Right mouse button pressed at global position:" << event->globalPos();}}
};

在这个示例中,MyWidget类重写了mousePressEvent函数,根据按下的鼠标按键不同,输出相应的位置信息。

(二)mouseReleaseEvent

  1. 函数名void QWidget::mouseReleaseEvent(QMouseEvent *event)
  2. 函数功能:在鼠标按键在部件上释放时被调用。常与mousePressEvent配合使用,完成一些与鼠标操作相关的功能,比如在绘图应用中,鼠标按下时开始绘制,释放时结束绘制。
  3. 函数参数QMouseEvent *event,包含鼠标释放事件的详细信息,与mousePressEvent中的参数类似。
  4. 函数返回值void,没有返回值,主要用于处理鼠标释放后的相关操作。
  5. 主要函数举例
class MyWidget : public QWidget {Q_OBJECTQPoint pressPos;
public:void mousePressEvent(QMouseEvent *event) override {if (event->button() == Qt::LeftButton) {pressPos = event->pos();}}void mouseReleaseEvent(QMouseEvent *event) override {if (event->button() == Qt::LeftButton) {QPoint releasePos = event->pos();int distance = (releasePos - pressPos).manhattanLength();qDebug() << "Mouse dragged for a distance of:" << distance;}}
};

此例中,MyWidget类在mousePressEvent中记录鼠标按下的位置,在mouseReleaseEvent中计算鼠标拖动的距离并输出。

(三)mouseDoubleClickEvent

  1. 函数名void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
  2. 函数功能:当鼠标在部件上双击时被调用。通常用于实现一些特殊的交互功能,如双击打开文件、放大视图等。
  3. 函数参数QMouseEvent *event,可获取双击事件的相关信息,如双击的位置、按键等。
  4. 函数返回值void,没有返回值,用于执行双击事件对应的操作。
  5. 主要函数举例
class MyWidget : public QWidget {Q_OBJECT
public:void mouseDoubleClickEvent(QMouseEvent *event) override {if (event->button() == Qt::LeftButton) {qDebug() << "Left mouse button double - clicked at:" << event->pos();}}
};

在这个示例中,当鼠标左键在MyWidget上双击时,输出双击的位置信息。

(四)mouseMoveEvent

  1. 函数名void QWidget::mouseMoveEvent(QMouseEvent *event)
  2. 函数功能:当鼠标在部件上移动时被调用。常用于实现实时响应鼠标移动的功能,如在绘图软件中实时绘制线条,或在游戏中根据鼠标移动控制角色方向。
  3. 函数参数QMouseEvent *event,通过它可以获取鼠标移动的详细信息,包括当前鼠标位置(pos())、移动过程中按下的按键(buttons())等。
  4. 函数返回值void,没有返回值,专注于处理鼠标移动相关逻辑。
  5. 主要函数举例
class MyWidget : public QWidget {Q_OBJECT
public:void mouseMoveEvent(QMouseEvent *event) override {if (event->buttons() & Qt::LeftButton) {qDebug() << "Mouse is being dragged with left button at:" << event->pos();}}
};

在这个例子中,当鼠标左键被按下并移动时,输出鼠标的当前位置信息。

三、QWidget的键盘事件处理函数

(一)keyPressEvent

  1. 函数名void QWidget::keyPressEvent(QKeyEvent *event)
  2. 函数功能:在键盘按键被按下时被调用。常用于实现各种键盘控制功能,如在游戏中通过键盘控制角色移动,在文本编辑器中处理按键输入等。
  3. 函数参数QKeyEvent *event,通过它可以获取按下按键的详细信息,如按键的键值(key(),用于识别具体按键)、本次事件中使用的键的个数(count())以及键上的文本内容(text())等。
  4. 函数返回值void,没有返回值,主要用于执行键盘按下事件对应的操作。
  5. 主要函数举例
class MyWidget : public QWidget {Q_OBJECT
public:void keyPressEvent(QKeyEvent *event) override {if (event->key() == Qt::Key_A) {qDebug() << "The 'A' key was pressed";} else if (event->key() == Qt::Key_Up) {qDebug() << "The up arrow key was pressed";}}
};

在此例中,MyWidget类重写了keyPressEvent函数,根据按下的不同按键输出相应信息。

(二)keyReleaseEvent

  1. 函数名void QWidget::keyReleaseEvent(QKeyEvent *event)
  2. 函数功能:当键盘按键被释放时被调用。可用于处理与按键释放相关的逻辑,如在一些需要长按按键触发特殊功能的场景中,按键释放时结束该功能。
  3. 函数参数QKeyEvent *event,包含按键释放事件的详细信息,与keyPressEvent中的参数类似。
  4. 函数返回值void,没有返回值,专注于处理按键释放后的操作。
  5. 主要函数举例
class MyWidget : public QWidget {Q_OBJECTbool isCtrlPressed = false;
public:void keyPressEvent(QKeyEvent *event) override {if (event->key() == Qt::Key_Control) {isCtrlPressed = true;}}void keyReleaseEvent(QKeyEvent *event) override {if (event->key() == Qt::Key_Control) {isCtrlPressed = false;qDebug() << "Ctrl key released";}}
};

在这个示例中,MyWidget类通过keyPressEventkeyReleaseEvent函数记录Ctrl键的按下和释放状态,并在Ctrl键释放时输出相应信息。

四、QWidget的定时器事件处理函数

  1. 函数名void QWidget::timerEvent(QTimerEvent *event)
  2. 函数功能:当定时器超时时被调用。在基于事件处理函数版本的定时器实现中,通过重写该函数来定义定时器超时后执行的操作,比如定时更新界面显示的时间、定时检查网络连接状态等。
  3. 函数参数QTimerEvent *event,通过它可以获取定时器的相关信息,如定时器的ID号(timerId()),用于区分不同的定时器(当存在多个定时器时)。
  4. 函数返回值void,没有返回值,主要用于执行定时器超时后的操作。
  5. 主要函数举例
class MyWidget : public QWidget {Q_OBJECTint timerId;
public:MyWidget(QWidget *parent = nullptr) : QWidget(parent) {timerId = startTimer(1000); // 启动一个每秒触发一次的定时器}void timerEvent(QTimerEvent *event) override {if (event->timerId() == timerId) {qDebug() << "Timer timeout. Current time:" << QTime::currentTime();}}
};

在这个例子中,MyWidget类启动了一个定时器,并在timerEvent函数中处理定时器超时事件,输出当前时间。

五、QWidget的绘制事件处理函数

  1. 函数名void QWidget::paintEvent(QPaintEvent *event)
  2. 函数功能:用于处理绘制事件,当窗口需要重新绘制时(如窗口大小改变、最小化后恢复、主动调用repaintupdate函数等情况),该函数会被自动调用。通常在这个函数中使用QPainter类进行各种图形绘制操作,如绘制文本、矩形、椭圆等。
  3. 函数参数QPaintEvent *event,包含了绘制事件的相关信息,虽然在实际绘制操作中可能较少直接使用,但它是绘制事件的标识。
  4. 函数返回值void,主要负责执行绘制操作,没有返回值。
  5. 主要函数举例
class MyWidget : public QWidget {Q_OBJECT
public:void paintEvent(QPaintEvent *event) override {QPainter painter(this);painter.setPen(Qt::blue);painter.setFont(QFont("Arial", 20));painter.drawText(rect(), Qt::AlignCenter, "Hello, Qt!");painter.drawRect(10, 10, width() - 20, height() - 20);}
};

在这个示例中,MyWidget类重写了paintEvent函数,使用QPainter在窗口中绘制了文本和矩形。

牛客试炼

相关文章:

QT修仙笔记 事件大圆满 闹钟大成

学习笔记 牛客刷题 闹钟 时钟显示 通过 QTimer 每秒更新一次 QLCDNumber 显示的当前时间&#xff0c;格式为 hh:mm:ss&#xff0c;实现实时时钟显示。 闹钟设置 使用 QDateTimeEdit 让用户设置闹钟时间&#xff0c;可通过日历选择日期&#xff0c;设置范围为当前时间到未来 …...

Leetcode - 149双周赛

目录 一、3438. 找到字符串中合法的相邻数字二、3439. 重新安排会议得到最多空余时间 I三、3440. 重新安排会议得到最多空余时间 II四、3441. 变成好标题的最少代价 一、3438. 找到字符串中合法的相邻数字 题目链接 本题有两个条件&#xff1a; 相邻数字互不相同两个数字的的…...

解决 ComfyUI-Impact-Pack 中缺少 UltralyticsDetectorProvider 节点的问题

解决 ComfyUI-Impact-Pack 中缺少 UltralyticsDetectorProvider 节点的问题 1. 安装ComfyUI-Impact-Pack 首先确保ComfyUI-Impact-Pack 已经下载 地址: https://github.com/ltdrdata/ComfyUI-Impact-Pack 2. 安装ComfyUI-Impact-Subpack 由于新版本的Impact Pack 不再提供这…...

使用Kickstart配置文件封装操作系统实现Linux的自动化安装

使用Kickstart配置文件封装操作系统实现Linux的自动化安装 创建ks.cfg配置文件 可以使用已经安装完成的Linux操作系统中的/root目录下的anaconda.cfg配置文件 注意&#xff0c;配置文件会因为kickstart的版本兼容性的问题导致无法安装报错需要在实际使用过程中删除某些参数 …...

Android笔记【snippet】

一、 6、Card及ConstraintLayout线性布局 //定义单独的机器人单独一行的卡片 Composable fun RobotCard(robot: Robot,navController:NavController){Card(modifier Modifier.fillMaxWidth().wrapContentHeight().padding(5.dp),colors CardDefaults.elevatedCardColors(co…...

zsh: command not found: conda

场景描述 在 Linux 服务器上使用 zsh 时&#xff0c;如果出现 zsh: command not found: conda 错误&#xff0c;说明你的系统未正确配置 conda 命令&#xff0c;或者你尚未安装 Anaconda/Miniconda。 解决方案 确保已安装 Anaconda 或 Miniconda conda 是 Anaconda 或 Minico…...

【知识科普】CPU,GPN,NPU知识普及

CPU,GPU,NPU CPU、GPU、NPU 详解1. CPU&#xff08;中央处理器&#xff09;2. GPU&#xff08;图形处理器&#xff09;3. NPU&#xff08;神经网络处理器&#xff09; **三者的核心区别****协同工作示例****总结** CPU、GPU、NPU 详解 1. CPU&#xff08;中央处理器&#xff0…...

【C++八股】struct和Class的区别

1. 默认访问控制 struct&#xff1a;结构体中的成员默认是 public&#xff0c;即外部代码可以直接访问结构体的成员。class&#xff1a;类中的成员默认是 private&#xff0c;即外部代码不能直接访问类的成员&#xff0c;必须通过公有接口&#xff08;通常是成员函数&#xff…...

鹧鸪云光伏仓储、物料管理软件详细功能

采购中心 &#xff1a;作为核心枢纽&#xff0c;能集中管理多品牌设备&#xff0c;企业可灵活按需采购。采购与退货流程高效便捷&#xff0c;审核通过后物资快速补充、问题货物及时退回&#xff0c;保障资金与物资顺畅周转&#xff0c;避免积压浪费。付款与退款环节 &#xff1…...

bazel 小白理解

Bazel命令是用于构建和测试软件项目的一个强大工具&#xff0c;尤其适用于大规模和多语言的软件项目。对于小白来说&#xff0c;可以这样理解Bazel及其命令&#xff1a; Bazel的基本概念 构建系统&#xff1a;Bazel是一个构建系统&#xff0c;它的主要任务是自动化地编译和链…...

MVC(Model-View-Controller)framework using Python ,Tkinter and SQLite

1.项目结构 sql: CREATE TABLE IF NOT EXISTS School (SchoolId TEXT not null, SchoolName TEXT NOT NULL,SchoolTelNo TEXT NOT NULL) 整体思路 Model&#xff1a;负责与 SQLite 数据库进行交互&#xff0c;包括创建表、插入、删除、更新和查询数据等操作。View&#xff1…...

WPF 设置宽度为 父容器 宽度的一半

方法1&#xff1a;使用 绑定和转换器 实现 创建类文件 HalfWidthConverter public class HalfWidthConverter : IValueConverter{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){if (value is double width){return width / 4…...

java项目之在线心理评测与咨询管理系统(源码+文档)

项目简介 在线心理评测与咨询管理系统实现了以下功能&#xff1a; 在线心理评测与咨询管理系统的主要使用者分为&#xff1a; &#xff08;1&#xff09;在个人中心&#xff0c;管理员可以修改自己的用户名和登录密码。 &#xff08;2&#xff09;在系统前台可以查看首页&…...

【STM32系列】利用MATLAB配合ARM-DSP库设计FIR数字滤波器(保姆级教程)

ps.源码放在最后面 设计IIR数字滤波器可以看这里&#xff1a;利用MATLAB配合ARM-DSP库设计IIR数字滤波器&#xff08;保姆级教程&#xff09; 前言 本篇文章将介绍如何利用MATLAB与STM32的ARM-DSP库相结合&#xff0c;简明易懂地实现FIR低通滤波器的设计与应用。文章重点不在…...

Springboot框架扩展功能的使用

Spring Boot 提供了许多扩展点&#xff0c;允许开发者在应用程序的生命周期中插入自定义逻辑。这些扩展点可以帮助你更好地控制应用程序的行为&#xff0c;例如在启动时初始化数据、在关闭时释放资源、或者自定义配置加载逻辑。以下是 Spring Boot 中常见的扩展点&#xff1a; …...

yum报错 Could not resolve host: mirrorlist.centos.org

检查dns 使用ping www.baidu.com &#xff0c;如果ping不通&#xff0c;检查/etc/resolv.conf文件中是否有&#xff1a; nameserver 8.8.8.8 nameserver 8.8.4.4 替换yum源 1.备份原始的 YUM 源配置文件&#xff1a; sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.r…...

docker使用dockerfile打包镜像(docker如何打包)

文章目录 1. 编写 Dockerfile2. 构建 Docker 镜像3. 运行 Docker 容器4. 导出与导入镜像&#xff08;可选&#xff09; 1. 编写 Dockerfile Dockerfile 是一个文本文件&#xff0c;其中包含了一系列指令&#xff0c;这些指令定义了如何构建你的 Docker 镜像。下面以一个简单的…...

去中心化AGI网络架构:下一代人工智能的范式革命

文章目录 引言:当AGI遇到去中心化一、中心化AI架构的四大困境1.1 算力垄断与资源错配1.2 数据孤岛与隐私悖论1.3 模型暴政与单点故障1.4 创新抑制与价值捕获二、去中心化AGI网络的架构设计2.1 分层架构总览2.2 网络层:混合拓扑结构2.3 计算层:动态算力编排2.4 数据层:零知识…...

gitlab无法登录问题

在我第一次安装gitlab的时候发现登录页面是 正常的页面应该是 这种情况的主要原因是不是第一次登录&#xff0c;所以我们要找到原先的密码 解决方式&#xff1a; [rootgitlab ~]# vim /etc/gitlab/initial_root_password# WARNING: This value is valid only in the followin…...

单向链表在实际项目中的应用

前言 在实际项目中&#xff0c;单向链表经常被用来解决排队问题&#xff0c;因为链表允许动态地添加和移除元素&#xff0c;非常适合模拟队列&#xff08;FIFO&#xff0c;先进先出&#xff09;的行为。 这里的链表包含头节点&#xff0c;头结点的数据用来记录链表长度&#x…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...