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

鸿蒙PC:Qt适配OpenHarmony实战【番茄刻】:工作和休息两种倒计时如何写成一个 QML 状态机

前言欢迎加入鸿蒙PC开发者社区共同打造开发者工具生态鸿蒙PC开发者社区 https://harmonypc.csdn.net/项目开源地址https://atomgit.com/lqjmac/qtfqk我更愿意把这类 Demo 当成工程切片来看功能要小链路要完整运行结果要能验证。本文记录第 23 个 Qt 适配鸿蒙小项目番茄刻。它的定位是番茄钟核心功能是工作倒计时、休息倒计时、开始暂停和轮次记录。番茄钟的业务很小但状态很明确运行中、暂停、专注、休息、完成轮次。番茄刻 的工程价值不是功能复杂而是把 Qt Quick、OpenHarmony HAP、QML 资源和窗口刷新串成一条可复现路径。提示本文按真实工程路径和真实 Bundle Name 编写命令可以直接对照项目目录执行。推荐阅读顺序确认项目目录、中文展示名和 Bundle Name。检查 Qt SDK 相对路径避免构建机路径绑定。运行构建、安装、启动和日志过滤命令。本文包含的重点元素项目截图配置表格构建命令QML 片段常见问题表一、为什么这个 Demo 值得单独写1.1 项目解决什么问题番茄刻不是为了把 番茄钟 做到复杂而是为了验证 Qt Quick 在鸿蒙桌面窗口里的完整链路。这个链路包含资源配置、Native CMake、QML 首屏、双入口导出、窗口自适应、HAP 构建和设备启动。主要功能如下工作倒计时默认 25 分钟休息倒计时默认 5 分钟开始暂停重置计时切换专注和休息模式记录完成轮次1.2 最终运行截图图 1番茄刻 在 OpenHarmony 桌面环境里的运行效果。1.3 关注点速览关注点为什么重要在本项目中的体现应用标识避免 25 个 Demo 安装冲突com.nutpi.fanqiekeQML 状态决定界面是否能即时反馈Timer 每秒扣减 remainingSeconds阶段结束后切换 workMode构建参数决定换机器后能否继续构建-DQT_PREFIX../qtforharmony启动入口避免白屏和符号缺失同时保留main和qtmain二、项目清单先对齐2.1 信息总览项目内容应用展示名番茄刻项目目录名QtPomodoroDemoBundle Namecom.nutpi.fanqiekeCMake projectfanqieke_pomodoro项目类型番茄钟核心功能工作倒计时、休息倒计时、开始暂停和轮次记录这张表建议和 README 中的信息保持一致。项目多了以后最怕的是展示名、包名和目录名互相错位。2.2 目录结构qt_for_harmony/ ├── qtforharmony/ ├── QtPomodoroDemo/ │ ├── AppScope/ │ ├── entry/ │ │ ├── build-profile.json5 │ │ └── src/main/cpp/ │ │ ├── CMakeLists.txt │ │ ├── main.cpp │ │ ├── main.qml │ │ └── qml.qrc │ └── README.md └── qt-docs/这里有一个朴素但重要的规则Qt SDK 放在项目同级目录不塞进每个 Demo 里面。2.3 模块职责模块作用检查点AppScope应用包名和展示名com.nutpi.fanqieke是否唯一entry/build-profile.json5native 构建参数Qt SDK 相对路径entry/src/main/cppC 入口和 QMLmain.qml是否进入 qrcREADME.md项目说明构建和启动命令是否完整三、从 UI 布局开始拆3.1 build-profile.json5项目需要使用相对路径指定 Qt SDK。当前工程使用的关键片段如下{ externalNativeOptions: { path: ./src/main/cpp/CMakeLists.txt, arguments: -DQT_PREFIX../qtforharmony, cppFlags: , abiFilters: [arm64-v8a] } }关键规则项目需要arguments: -DQT_PREFIX../qtforharmonySDK 文件请到文末保留的 SDK 仓库自取并放到项目同级目录qtforharmony中。3.2 CMakeLists.txtcmake_minimum_required(VERSION 3.5.0) project(fanqieke_pomodoro) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../.. ABSOLUTE) if (NOT IS_ABSOLUTE ${QT_PREFIX}) get_filename_component(QT_PREFIX ${PROJECT_ROOT}/${QT_PREFIX} ABSOLUTE) endif() list(PREPEND CMAKE_PREFIX_PATH ${QT_PREFIX}) find_package(Qt5 REQUIRED COMPONENTS Core Gui Qml Quick QuickControls2) add_library(entry SHARED main.cpp qml.qrc)这段配置先把相对的QT_PREFIX转成绝对路径再交给 CMake 查找 Qt。3.3 qml.qrcRCCqresourceprefix/filemain.qml/file/qresource/RCC把 QML 打进 Qt 资源系统后运行时可以统一通过qrc:/main.qml加载。四、数据模型放在哪里4.1 首屏布局左侧大倒计时圆盘右侧流程提示和本地状态卡片。这种布局不是为了炫技而是为了让 Demo 的功能一眼就能被看懂。4.2 根节点尺寸策略Rectangle { id: root width: 960 height: 1080 color: #F5F6FA property real margin: Math.max(20, Math.min(48, width * 0.042)) property real gap: Math.max(12, Math.min(24, width * 0.022)) property real titleSize: Math.max(34, Math.min(58, width * 0.054)) }根节点给出默认尺寸真正运行时由QQuickView::SizeRootObjectToView接管。4.3 本项目的数据模型ListModel { id: demoModel ListElement { name: 示例项一; state: ready } ListElement { name: 示例项二; state: active } ListElement { name: 示例项三; state: done } }实际工程中番茄刻 使用的是stepModel。这些数据都在 QML 内部适合单机演示。五、Qt for Harmony 的启动细节5.1 函数职责表函数职责timeText()封装业务逻辑toggleRunning()处理用户操作resetTimer()恢复或清理状态setWorkMode()切换当前展示内容finishCurrentRound()封装业务逻辑这些函数没有故意抽得很复杂。Demo 项目最重要的是让读者能从 QML 文件里直接看懂状态从哪里来、又流向哪里。5.2 典型交互片段MouseArea { anchors.fill: parent onClicked: { // 点击后修改模型状态界面绑定会自动刷新 demoModel.setProperty(index, state, done) } }点击事件只负责改变状态展示层通过绑定更新这比手动到处刷新文本更稳。5.3 业务函数示意function demoFlow(row) { var current row var before demoModel.count demoModel.setProperty(row, state, done) return before }这段不是要照搬而是说明当前项目的函数组织方式先从模型拿当前数据再执行用户动作最后让绑定表达式刷新界面六、把 HAP 构建出来6.1 保留双入口externCvoidqtmain(){staticResponsiveQuickView*viewnullptr;if(view!nullptr){return;}configureSurfaceFormat();viewnewResponsiveQuickView();loadQml(view);}intmain(intargc,char*argv[]){configureSurfaceFormat();QGuiApplicationapp(argc,argv);ResponsiveQuickView view;if(!loadQml(view)){return-1;}returnapp.exec();}之前遇到过只导出qtmain时运行时报Symbol not found: main的情况所以这一批 Qt Demo 都统一保留两个入口。6.2 标题和 QML 加载boolloadQml(ResponsiveQuickView*view){view-setTitle(QStringLiteral(番茄刻));view-setSource(QUrl(QStringLiteral(qrc:/main.qml)));if(view-status()QQuickView::Error){qWarning()Failed to load qrc:/main.qml;returnfalse;}view-showResponsive();returntrue;}这里标题要和应用展示名保持一致。运行时如果日志出现 QML 加载失败优先检查qml.qrc。七、安装启动与截图7.1 构建 HAPcdQtPomodoroDemo /Users/luqingjiedemac/ohos/command-line-tools/bin/hvigorw assembleHap--stacktrace构建完成后HAP 默认输出在下面这个路径entry/build/default/outputs/default/entry-default-unsigned.hap7.2 安装和启动hdcinstall-rentry/build/default/outputs/default/entry-default-unsigned.hap hdc shell aa start-aEntryAbility-bcom.nutpi.fanqieke-mentry启动命令里的 Bundle Name 必须和AppScope/app.json5一致。7.3 构建失败先看哪里QT_PREFIX是否指向同级qtforharmony。CMakeLists.txt的 project 名称是否已经替换。main.qml是否存在于qml.qrc中。八、排错记录8.1 过滤关键日志hdc shell hilog-x-z500|rg-nQtForOpenHarmony|QPAForOpenHarmony|fanqieke|Failed|failed|Error|error|qrc|main function|Symbol not found|QML|ReferenceError|TypeError我重点看这些信号是否出现Symbol not found: main是否出现Failed to load qrc:/main.qml是否出现 QML 的ReferenceError或TypeError是否能看到应用进程还在运行8.2 截图命令hdc shell snapshot_display-f/data/local/tmp/fanqieke_screen.jpeg hdcfilerecv /data/local/tmp/fanqieke_screen.jpeg ./qt-docs/assets/fanqieke-screen.jpeg截图不是装饰它是确认首屏真的渲染出来的证据。8.3 当前项目验证点开始后秒数减少暂停后计时停止完成专注后进入休息注意文章里提到的业务数据都是 QML 内置示例数据不代表已经接入系统能力或外部服务。九、改造成产品前的检查9.1 常见问题表现象可能原因处理方式白屏QML 没加载成功或窗口未刷新检查qrc:/main.qml和日志找不到 main只保留了qtmain同时导出main和qtmain构建找不到 QtQT_PREFIX路径错误使用-DQT_PREFIX../qtforharmony启动失败Bundle Name 写错对照com.nutpi.fanqieke窗口缩放不刷新根对象没有跟随窗口尺寸使用响应式QQuickView刷新策略9.2 排查顺序先看 HAP 是否重新构建。再看安装的包名是不是当前项目。然后看日志里有没有 QML 或 main 符号错误。最后才去调整具体控件布局。十、还能继续加什么10.1 可以继续做的功能增加自定义时长加入结束提示音保存每日番茄数量这些扩展不建议一口气全做。Qt 适配鸿蒙的早期样例优先目标应该是结构稳定、运行稳定、验证路径稳定。10.2 工程增强方向QtObject { id: appState property int currentIndex: 0 property bool dirty: false property string message: ready }当页面状态继续变多可以把零散属性收进一个QtObject这样顶层不会越来越乱。10.3 清理和重建rm-rfentry/build entry/.cxx .hvigor /Users/luqingjiedemac/ohos/command-line-tools/bin/hvigorw assembleHap--stacktrace遇到缓存比较顽固的问题时可以清掉构建产物后重建。正常开发时不需要每次都清理。十一、资料保留11.1 OpenHarmony 文档入口OpenHarmony 文档中心https://docs.openharmony.cn/11.2 Qt for Harmony SDK 仓库Qt for Harmony SDK 仓库https://atomgit.com/nutpi/qtforharmony_sdk11.3 为什么只保留三个链接这批文章用于项目发布和读者复现。链接过多会分散注意力所以正文只保留社区入口、OpenHarmony 文档和 Qt SDK 仓库三个入口。总结番茄刻 这个 Demo 的重点是工作倒计时、休息倒计时、开始暂停和轮次记录。从工程角度看它已经覆盖了 Qt for OpenHarmony 项目里最关键的几步配置 Qt SDK、打包 QML、保留双入口、构建 HAP、安装启动和截图验证。如果你也在做 Qt 适配鸿蒙可以先用这种小项目把链路跑稳再逐步接入更真实的数据和业务。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力

相关文章:

鸿蒙PC:Qt适配OpenHarmony实战【番茄刻】:工作和休息两种倒计时如何写成一个 QML 状态机

前言 欢迎加入鸿蒙PC开发者社区,共同打造开发者工具生态:鸿蒙PC开发者社区 :https://harmonypc.csdn.net/ 项目开源地址:https://atomgit.com/lqjmac/qtfqk 我更愿意把这类 Demo 当成工程切片来看:功能要小&#xf…...

手把手教你:把Ubuntu 20.04完整系统塞进U盘,打造随身便携开发环境

手把手打造Ubuntu 20.04便携开发环境:从镜像制作到硬件兼容全指南 在咖啡厅调试代码时发现环境配置丢失?出差临时借用同事电脑却无法运行你的开发工具?这些困扰程序员多年的痛点,其实只需要一个装满完整Ubuntu系统的U盘就能彻底解…...

别再让Ubuntu22.04时间错乱了!用hwclock和timedatectl搞定硬件时钟时区的保姆级教程

彻底解决Ubuntu 22.04时间同步问题:硬件时钟与时区管理权威指南你是否曾在双系统切换后发现Ubuntu显示的时间比实际快了8小时?或者每次重启后系统时间都会"跳票"?这些看似小问题背后,隐藏着操作系统与硬件时钟&#xff…...

直接去偏机器学习:用Bregman散度统一因果推断与协变量平衡

1. 项目概述与核心动机在因果推断、政策评估乃至更广泛的计量经济学和机器学习应用中,我们常常关心一个“目标参数”,比如平均处理效应(ATE)——也就是某项干预或政策对结果的平均影响。传统上,一个非常自然的想法是&a…...

Seraphine:英雄联盟玩家的智能游戏助手完整指南

Seraphine:英雄联盟玩家的智能游戏助手完整指南 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine Seraphine是一款基于英雄联盟官方LCU API开发的智能游戏助手,专为《英雄联盟》玩家设计…...

基于机器学习与RIS的毫米波用户角度定位:四波束探测实现低开销波束管理

1. 项目概述:当RIS遇见机器学习,如何用四个波束“锁定”用户? 在毫米波频段玩无线通信,就像在一条狭窄却充满障碍物的高速公路上开跑车。速度是快了,但一个不小心,信号就被墙、人甚至一片树叶给“堵”得严严…...

BepInEx 6.0技术揭秘:如何构建跨平台Unity插件框架的5大核心机制

BepInEx 6.0技术揭秘:如何构建跨平台Unity插件框架的5大核心机制 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx 在Unity游戏开发领域,插件框架的技术实现一…...

猫抓:5步掌握网页资源嗅探工具,轻松下载全网视频

猫抓:5步掌握网页资源嗅探工具,轻松下载全网视频 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 还在为网页上的精彩视频无…...

Terraform 实战:用 for 表达式将列表元素转换为大写

Terraform 技巧:使用 for 表达式将列表元素转换为大写 在 Terraform 配置中,我们经常需要对列表中的字符串进行批量转换,例如将小写名称统一转为大写,以满足某些标签规范或命名约定。本文以 var.names 列表为例,演示如何通过 for 表达式结合 upper 函数,生成一个全大写的…...

迁移学习与随机森林在乳腺癌预后模型中的实践与优化

1. 项目概述与核心价值在临床肿瘤学,尤其是乳腺癌治疗领域,一个精准的预后模型不仅是冰冷的统计工具,更是连接医生决策与患者希望的生命线。传统的预后工具,如基于临床病理特征的诺丁汉预后指数或更现代的基因组学工具&#xff08…...

OpenClaw 架构解析:Skill 与 Agent 的设计哲学与实现机制

摘要:本文深入剖析 OpenClaw 框架中 Skill 和 Agent 的核心概念、设计理念及协同机制,帮助开发者理解其模块化架构,并掌握最佳实践。 背景与问题 为什么需要 Skill? 在构建 AI Agent 系统时,我们面临几个核心挑战&am…...

深度学习在碳离子治疗剂量计算中的应用:U-Net、GAN与扩散模型对比

1. 项目概述:当深度学习遇上碳离子治疗剂量计算在放射治疗领域,尤其是像碳离子治疗这样的先进粒子疗法中,剂量计算的精度和速度是决定治疗成败的关键。碳离子因其独特的“布拉格峰”物理特性,能够将高剂量能量精准地沉积在肿瘤靶区…...

告别误报!用SCTransNet+Transformer搞定红外小目标检测(附PyTorch实战代码)

突破红外小目标检测瓶颈:SCTransNet与Transformer的实战融合在安防监控、遥感测绘和军事预警等关键领域,红外小目标检测技术正面临前所未有的挑战。当目标尺寸小于1010像素、信噪比低于2dB时,传统算法在复杂背景下的误报率往往高达30%以上。这…...

中医馆升级|结合瑞式养老模式的医养结合完整落地方案

传统中医馆最大瓶颈是:客流老化、单次交易、依赖坐诊、复购不稳定、没有社区刚需流量。中医馆最高级的升级路径,不是继续做针灸开药,而是转型社区银发康养中心,嫁接瑞式养老标准化体系,打造「中医诊疗瑞式社区养老」双…...

topcode【随机算法题】【2026.5.24打卡-java版本】

最长有效括号 要点&#xff1a;栈&#xff0c;push下标 class Solution {public int longestValidParentheses(String s) {//栈//放前哨-1Deque<Integer> stack new ArrayDeque<>();stack.push(-1);int ans 0;for(int i 0; i < s.length(); i){char c s.…...

5分钟上手:用LeaguePrank打造专属英雄联盟客户端

5分钟上手&#xff1a;用LeaguePrank打造专属英雄联盟客户端 【免费下载链接】LeaguePrank 项目地址: https://gitcode.com/gh_mirrors/le/LeaguePrank 想要让你的英雄联盟客户端界面变得与众不同吗&#xff1f;LeaguePrank是一款基于官方LCU API开发的英雄联盟客户端美…...

《道德经》第二十章

本章以绝学无忧我独昏昏为核心&#xff0c;专讲体道者超越世俗价值、回归生命本源的精神境界&#xff0c;是老子自我写照式的抒情篇章。以“唯阿善恶相去几何”的追问破题&#xff0c;以“众人熙熙”与“我独泊兮”的强烈对比展开&#xff0c;最终以“贵食母”点明与道合一的生…...

华硕笔记本终极优化指南:如何用G-Helper轻量级工具全面提升使用体验

华硕笔记本终极优化指南&#xff1a;如何用G-Helper轻量级工具全面提升使用体验 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook…...

别再折腾VMware Tools了!用FileZilla+SSH搞定Windows与Ubuntu虚拟机文件互传(保姆级教程)

告别VMware Tools烦恼&#xff1a;SSHFileZilla实现跨平台文件传输全攻略 每次在Windows和Ubuntu虚拟机之间传输文件时&#xff0c;VMware Tools总是给你带来各种麻烦&#xff1f;安装失败、兼容性问题、功能受限...这些问题我都经历过。今天我要分享的是一种更稳定、更通用的…...

[特殊字符] 旋转排序数组中的高效搜索:从线性到二分查找的进阶之路

给定一个由不同元素构成的旋转排序数组&#xff08;原本是升序排列&#xff0c;但在某个未知点进行了旋转&#xff09;&#xff0c;要求快速找到目标元素的索引。如果不存在&#xff0c;则返回 -1。 示例 1&#xff1a; 输入&#xff1a;arr [5, 6, 7, 8, 9, 10, 1, 2, 3], …...

VMware Workstation Pro 17上快速体验Rocky Linux 8.6:从镜像下载到命令行登录的5分钟极简流程

VMware Workstation Pro 17极速部署Rocky Linux 8.6实战指南 当技术爱好者们想要快速搭建一个Linux测试环境时&#xff0c;繁琐的安装流程往往会消耗大量时间。本文将展示如何在VMware Workstation Pro 17上&#xff0c;用最短时间完成Rocky Linux 8.6的部署&#xff0c;从零开…...

告别无效编程!Cursor + 高德地图实战,解锁AI开发效率密码

当GitHub Copilot还在逐行补全代码时&#xff0c;Cursor已经让开发者用"聊天"的方式写项目了。从Cursor的四大快捷键到AI幻觉的实战应对&#xff0c;从Vibe Coding的前沿理念到高德地图的AI落地实践&#xff0c;本文将带你深度理解AI编程的现在与未来。 目录 一、Cur…...

终极指南:5分钟解决BepInEx插件框架的90%常见问题 [特殊字符]

终极指南&#xff1a;5分钟解决BepInEx插件框架的90%常见问题 &#x1f680; 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx BepInEx是Unity游戏社区中最受欢迎的插件框架之一&…...

Unity Mecanim根运动偏转原理与四层解决方案

1. 这个问题不是Bug&#xff0c;是Mecanim对“根运动”最诚实的执行你有没有遇到过这样的情况&#xff1a;一个角色模型在Unity里播放完一段奔跑动画后&#xff0c;整个人歪着身子斜插进地面&#xff1b;或者转身动画播完&#xff0c;角色原地旋转了360度还多转了45度&#xff…...

Appium Android自动化环境四段链路深度验证指南

1. 这不是装几个软件就能跑起来的事&#xff1a;为什么90%的人卡在环境搭建第一步 “PythonAndroidAppium App自动化测试环境搭建”——光看标题&#xff0c;很多人第一反应是&#xff1a;不就是装Python、配JDK、下Android SDK、跑个appium命令&#xff1f;我试过三次&#x…...

Charles断点调试:HTTP/HTTPS流量精准控制与实战避坑

1. 这不是“抓包”&#xff0c;是精准外科手术式调试 很多人第一次听说 Charles&#xff0c;第一反应是“哦&#xff0c;又一个抓包工具”。但如果你真这么用&#xff0c;大概率会在某次接口联调中卡住两小时&#xff0c;反复刷新页面却始终看不到后端返回的错误码&#xff0c…...

Burp Suite Professional实战卡点解析:HTTPS抓包、代理拦截与Intruder失效根因

1. 这不是“点开就能用”的工具&#xff0c;而是Web安全工程师的呼吸节奏很多人第一次打开Burp Suite Professional&#xff0c;盯着那个灰色的拦截开关发呆——明明浏览器配置了代理&#xff0c;HTTPS网站也装了CA证书&#xff0c;可流量就是不进Intruder、Repeater里不动如山…...

机器学习记忆化:平衡隐私、鲁棒性与公平性的核心技术挑战

1. 项目概述&#xff1a;当机器学习开始“记住”数据时&#xff0c;我们面临什么&#xff1f;在构建一个机器学习模型时&#xff0c;我们总希望它能像一位聪明的学生&#xff0c;不仅记住课本上的例题&#xff0c;更能理解背后的原理&#xff0c;从而在考场上举一反三。但现实往…...

基于Transformer的行星大气辐射传输仿真器:百倍加速与1%精度

1. 项目概述&#xff1a;用Transformer重塑行星大气辐射传输计算在行星科学和天体物理领域&#xff0c;模拟一颗行星的大气层如何吸收、散射和发射星光与热辐射&#xff0c;是理解其气候、演化乃至潜在宜居性的基石。这个过程的核心&#xff0c;就是辐射传输计算。无论是预测即…...

RL-ARM CAN迁移至CMSIS-RTOS的实践指南

1. 从RL-ARM CAN到CMSIS-RTOS的迁移背景在嵌入式开发领域&#xff0c;随着Keil MDK版本的迭代&#xff0c;RL-ARM库中的CAN组件逐渐向MDK Middleware过渡。许多基于MDK v4和早期v5版本开发的项目&#xff0c;都使用了RL-ARM库中的CAN驱动实现。当开发者需要将项目升级到较新的M…...