首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Qt for HarmonyOS PC 时钟应用开发实践

Qt for HarmonyOS PC 时钟应用开发实践

作者头像
徐建国
发布2025-11-29 15:08:07
发布2025-11-29 15:08:07
2570
举报
文章被收录于专栏:个人路线个人路线

📋 教程概述

本教程将手把手教你使用 Qt QML 在 HarmonyOS PC 平台上开发一个功能完整、界面精美的时钟应用。从零开始,逐步实现实时时钟显示、日期显示、12/24 小时制切换等功能。

🎯 学习目标

通过本教程,你将学会:

  • ✅ 使用 QML 创建现代化 UI 界面
  • ✅ 使用 Timer 组件实现实时更新
  • C++ 与 QML 集成:创建 C++ 类并暴露给 QML
  • Q_INVOKABLE 宏的使用和原理
  • ✅ 日期时间格式化技巧(C++ 和 JavaScript)
  • ✅ 渐变背景和视觉效果设计
  • ✅ 用户交互处理(点击切换功能)
  • ✅ OpenGL ES 表面格式配置
  • ✅ CMake 构建配置

📱 最终效果

  • 实时时钟:每秒自动更新的时:分:秒显示
  • 日期显示:年月日和星期几(C++ 实现)
  • 交互功能:点击屏幕切换 12/24 小时制
  • 精美界面:渐变背景和发光效果
  • 响应式布局:适配不同屏幕尺寸
  • 高性能:核心逻辑使用 C++ 实现
  • 跨平台:支持手机、平板、PC

📚 前置知识

需要了解的技术

必须掌握
  • Qt QML 基础语法
  • C++ 基础(类、继承、指针)
  • CMake 基础
建议了解
  • JavaScript 基础
  • Qt 元对象系统(MOC)
  • 日期时间处理

开发环境

  • DevEco Studio 5.0+
  • Qt for OpenHarmony SDK
  • HarmonyOS 模拟器或真机
  • 鸿蒙 PC:支持 aarch64 架构(可选)

平台支持

本教程开发的应用支持多平台运行:

  • ✅ HarmonyOS 手机
  • ✅ HarmonyOS 平板
  • 鸿蒙 PC(桌面应用)
  • ✅ HarmonyOS 模拟器

🚀 步骤一:创建项目基础结构

1.1 创建 main.qml 文件

首先,创建一个基本的 QML 窗口结构:

代码语言:javascript
复制
// main.qml - 基础结构
import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 800
    height: 1200
    visible: true
    title: "Qt 时钟 for 鸿蒙"

    Rectangle {
        anchors.fill: parent
        color: "#2C5364"
    }
}

代码说明

  • Window:创建应用窗口
  • width/height:设置窗口尺寸
  • Rectangle:填充整个窗口作为背景

1.2 运行验证

此时运行应用,应该看到一个纯色背景的窗口。


🎨 步骤二:设计渐变背景

2.1 添加渐变效果

使用 Gradient 组件创建美观的渐变背景:

代码语言:javascript
复制
Rectangle {
    anchors.fill: parent
    gradient: Gradient {
        GradientStop { position: 0.0; color: "#0F2027" }
        GradientStop { position: 0.5; color: "#203A43" }
        GradientStop { position: 1.0; color: "#2C5364" }
    }
}

技术要点

  • Gradient:定义渐变效果
  • GradientStop:设置渐变节点
  • position:0.0(顶部)到 1.0(底部)
  • color:每个节点的颜色

颜色选择

  • #0F2027:深蓝灰色(顶部)
  • #203A43:中蓝色(中间)
  • #2C5364:浅蓝灰色(底部)

效果:创建从上到下的平滑渐变,营造深邃海洋的视觉感受。


⏰ 步骤三:实现时钟显示

3.1 添加时钟文本组件

在 Rectangle 内部添加时间显示:

代码语言:javascript
复制
Rectangle {
    anchors.fill: parent
    gradient: Gradient {
        // ... 渐变代码
    }

    // 添加时钟显示
    Text {
        id: timeDisplay
        text: Qt.formatTime(new Date(), "hh:mm:ss")
        font.pixelSize: 120
        font.bold: true
        font.family: "Arial"
        color: "#FFFFFF"
        anchors.centerIn: parent

        // 发光效果
        style: Text.Outline
        styleColor: "#00D4FF"
    }
}

代码详解

基础属性
代码语言:javascript
复制
id: timeDisplay              // 组件唯一标识
text: Qt.formatTime(...)     // 显示内容
font.pixelSize: 120          // 字体大小
font.bold: true              // 粗体
color: "#FFFFFF"             // 白色
Qt.formatTime() 函数
代码语言:javascript
复制
Qt.formatTime(new Date(), "hh:mm:ss")
  • new Date():获取当前时间
  • "hh:mm:ss":格式化为 时:分:秒
  • hh:24 小时制的小时(00-23)
  • mm:分钟(00-59)
  • ss:秒(00-59)
发光效果
代码语言:javascript
复制
style: Text.Outline          // 描边样式
styleColor: "#00D4FF"        // 青色描边

3.2 运行验证

此时应该看到一个大号的白色时间显示,带有青色发光效果。但是,时间是静态的,不会更新


🔄 步骤四:实现实时更新

4.1 添加 Timer 组件

使用 Timer 让时钟每秒自动更新:

代码语言:javascript
复制
Rectangle {
    anchors.fill: parent

    Text {
        id: timeDisplay
        // ... 时钟显示代码
    }

    // 添加定时器
    Timer {
        interval: 1000       // 1000毫秒 = 1秒
        running: true        // 自动启动
        repeat: true         // 重复执行
        onTriggered: {
            // 每秒执行一次
            var currentTime = new Date()
            timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")
        }
    }
}

Timer 组件详解

属性

说明

取值

interval

触发间隔(毫秒)

1000 = 1 秒

running

是否运行

true/false

repeat

是否重复

true = 持续触发

onTriggered

触发时的回调

JavaScript 代码

为什么需要 var currentTime?

代码语言:javascript
复制
// 每次获取最新时间
var currentTime = new Date()
timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")

这样可以确保每秒都获取系统的最新时间,而不是使用旧的时间对象。

4.2 运行验证

现在时钟应该每秒自动更新了!🎉


📅 步骤五:添加日期显示

5.1 创建布局结构

使用 Column 组织时钟和日期:

代码语言:javascript
复制
Column {
    anchors.centerIn: parent
    spacing: 40              // 子元素间距

    // 时钟显示
    Text {
        id: timeDisplay
        text: Qt.formatTime(new Date(), "hh:mm:ss")
        font.pixelSize: 120
        font.bold: true
        color: "#FFFFFF"
        anchors.horizontalCenter: parent.horizontalCenter
        style: Text.Outline
        styleColor: "#00D4FF"
    }

    // 日期显示
    Text {
        id: dateDisplay
        text: Qt.formatDate(new Date(), "yyyy年MM月dd日")
        font.pixelSize: 36
        color: "#B0E0E6"
        anchors.horizontalCenter: parent.horizontalCenter
    }
}

Qt.formatDate() 格式说明

格式符

说明

示例

yyyy

4 位年份

2025

MM

2 位月份

01-12

dd

2 位日期

01-31

年月日

中文字符

直接显示

完整示例:

代码语言:javascript
复制
Qt.formatDate(new Date(), "yyyy年MM月dd日")
// 输出:2025年11月06日

5.2 更新 Timer

在 Timer 的 onTriggered 中同时更新日期:

代码语言:javascript
复制
Timer {
    interval: 1000
    running: true
    repeat: true
    onTriggered: {
        var currentTime = new Date()
        timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")
        dateDisplay.text = Qt.formatDate(currentTime, "yyyy年MM月dd日")
    }
}

📆 步骤六:使用 C++ 实现星期显示

为什么使用 C++?

在 Qt 开发中,我们可以选择使用 JavaScript 或 C++ 来实现业务逻辑。对于星期显示功能,使用 C++ 有以下优势:

特性

JavaScript

C++

性能

较慢

快速

类型安全

弱类型

强类型

代码复用

仅 QML

可跨平台复用

调试

较难

工具完善

维护性

中等

更好

本教程选择 C++ 来展示如何将 C++ 逻辑暴露给 QML,这是 Qt 开发的最佳实践之一。


6.1 创建 DateHelper 头文件

首先在 entry/src/main/cpp/ 目录下创建 DateHelper.h

代码语言:javascript
复制
// DateHelper.h
#ifndef DATEHELPER_H
#define DATEHELPER_H

#include <QObject>
#include <QDateTime>
#include <QString>

class DateHelper : public QObject
{
    Q_OBJECT

public:
    explicit DateHelper(QObject *parent = nullptr);

    // Q_INVOKABLE 使方法可以在 QML 中调用
    Q_INVOKABLE QString getWeekDay();
    Q_INVOKABLE QString getWeekDayEnglish();
    Q_INVOKABLE int getWeekDayNumber();

signals:

public slots:
};

#endif // DATEHELPER_H

代码详解

Q_OBJECT 宏
代码语言:javascript
复制
Q_OBJECT
  • Qt 元对象系统的核心
  • 支持信号/槽机制
  • 支持属性系统
  • 必须添加才能使用 Qt 特性
Q_INVOKABLE 宏
代码语言:javascript
复制
Q_INVOKABLE QString getWeekDay();
  • 标记方法可以在 QML 中调用
  • 不需要声明为 public slots
  • 支持返回值和参数
三个方法说明

方法

返回值

说明

getWeekDay()

QString

中文星期(星期一)

getWeekDayEnglish()

QString

英文星期(Monday)

getWeekDayNumber()

int

数字(1-7)


6.2 实现 DateHelper 类

创建 DateHelper.cpp 实现文件:

代码语言:javascript
复制
// DateHelper.cpp
#include "DateHelper.h"

DateHelper::DateHelper(QObject *parent)
    : QObject(parent)
{
}

// 获取中文星期
QString DateHelper::getWeekDay()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    int dayOfWeek = currentDateTime.date().dayOfWeek();

    QStringList weekDays;
    weekDays << "星期一" << "星期二" << "星期三" << "星期四"
             << "星期五" << "星期六" << "星期日";

    // Qt 的 dayOfWeek() 返回 1-7 (1=Monday, 7=Sunday)
    return weekDays[dayOfWeek - 1];
}

// 获取英文星期
QString DateHelper::getWeekDayEnglish()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    return currentDateTime.toString("dddd");
}

// 获取星期数字 (1-7)
int DateHelper::getWeekDayNumber()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    return currentDateTime.date().dayOfWeek();
}

代码详解

QDateTime vs JavaScript Date

C++ 方式

代码语言:javascript
复制
QDateTime currentDateTime = QDateTime::currentDateTime();
int day = currentDateTime.date().dayOfWeek();  // 1-7

JavaScript 方式

代码语言:javascript
复制
var date = new Date();
var day = date.getDay();  // 0-6 (0=Sunday)

关键区别

  • C++:1=Monday, 7=Sunday
  • JavaScript:0=Sunday, 6=Saturday
QStringList 操作
代码语言:javascript
复制
QStringList weekDays;
weekDays << "星期一" << "星期二" << "星期三";
  • << 操作符:追加元素
  • 索引从 0 开始
  • 支持 Unicode(中文)
toString() 格式化
代码语言:javascript
复制
currentDateTime.toString("dddd")
  • dddd:完整星期名称(Monday)
  • ddd:缩写星期名称(Mon)
  • 支持多种格式化选项

6.3 更新 CMakeLists.txt

entry/src/main/cpp/CMakeLists.txt 中添加新文件:

代码语言:javascript
复制
# 添加 DateHelper.cpp 和 DateHelper.h
add_library(entry SHARED
    main.cpp
    DateHelper.cpp
    DateHelper.h
    qml.qrc
)

完整配置

代码语言:javascript
复制
cmake_minimum_required(VERSION 3.5.0)
project(qtdemo)

set(CMAKE_AUTOMOC ON)  # 自动处理 MOC (元对象编译器)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

# ... 其他配置 ...

# 添加源文件
add_library(entry SHARED
    main.cpp
    DateHelper.cpp
    DateHelper.h
    qml.qrc
)

# 链接 Qt 库
target_link_libraries(entry PRIVATE
    Qt${QT_VERSION_MAJOR}::Core
    Qt${QT_VERSION_MAJOR}::Qml
    Qt${QT_VERSION_MAJOR}::Quick
    # ... 其他库 ...
)

CMAKE_AUTOMOC 说明

  • 自动运行 MOC(Meta-Object Compiler)
  • 处理 Q_OBJECT 宏
  • 生成元对象代码
  • 必须开启才能使用信号/槽

6.4 在 main.cpp 中注册 C++ 对象

修改 main.cpp,将 DateHelper 暴露给 QML:

代码语言:javascript
复制
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "DateHelper.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // 创建 DateHelper 实例
    DateHelper dateHelper;

    // 将 C++ 对象注册到 QML 上下文
    engine.rootContext()->setContextProperty("dateHelper", &dateHelper);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

代码详解

setContextProperty()
代码语言:javascript
复制
engine.rootContext()->setContextProperty("dateHelper", &dateHelper);

参数

说明

第一个参数

QML 中的对象名称(字符串)

第二个参数

C++ 对象的指针

效果

  • 在 QML 中可以直接使用 dateHelper
  • 访问其所有 Q_INVOKABLE 方法
  • 类似于全局对象
生命周期管理
代码语言:javascript
复制
DateHelper dateHelper;  // 栈对象
engine.rootContext()->setContextProperty("dateHelper", &dateHelper);

注意

  • dateHelper 必须在整个应用生命周期内有效
  • 这里使用栈对象,在 main() 函数结束前一直有效
  • 也可以使用堆对象:DateHelper *dateHelper = new DateHelper();

6.5 在 QML 中调用 C++ 方法

修改 main.qml,使用 C++ 实现的星期功能:

代码语言:javascript
复制
Column {
    anchors.centerIn: parent
    spacing: 40

    // 时钟显示
    Text {
        id: timeDisplay
        text: Qt.formatTime(new Date(), "hh:mm:ss")
        font.pixelSize: 120
        font.bold: true
        color: "#FFFFFF"
        anchors.horizontalCenter: parent.horizontalCenter
        style: Text.Outline
        styleColor: "#00D4FF"
    }

    // 日期和星期
    Column {
        spacing: 10
        anchors.horizontalCenter: parent.horizontalCenter

        Text {
            id: dateDisplay
            text: Qt.formatDate(new Date(), "yyyy年MM月dd日")
            font.pixelSize: 36
            color: "#B0E0E6"
            anchors.horizontalCenter: parent.horizontalCenter
        }

        // 使用 C++ 实现的星期显示
        Text {
            id: weekDisplay
            text: dateHelper.getWeekDay()  // 调用 C++ 方法
            font.pixelSize: 28
            color: "#87CEEB"
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }
}

关键点

调用 C++ 方法
代码语言:javascript
复制
text: dateHelper.getWeekDay()
  • dateHelper:在 C++ 中注册的对象名
  • getWeekDay():C++ 中的 Q_INVOKABLE 方法
  • 语法与调用 JavaScript 函数完全相同
更新 Timer
代码语言:javascript
复制
Timer {
    interval: 1000
    running: true
    repeat: true
    onTriggered: {
        var currentTime = new Date()
        timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")
        dateDisplay.text = Qt.formatDate(currentTime, "yyyy年MM月dd日")
        weekDisplay.text = dateHelper.getWeekDay()  // 调用 C++ 方法
    }
}

6.6 JavaScript vs C++ 实现对比

JavaScript 实现(旧方法)
代码语言:javascript
复制
Rectangle {
    // JavaScript 函数
    function getWeekDay() {
        var days = ["星期日", "星期一", "星期二", "星期三",
                    "星期四", "星期五", "星期六"]
        return days[new Date().getDay()]
    }

    Text {
        text: getWeekDay()  // 调用 QML 函数
    }
}
C++ 实现(推荐)
代码语言:javascript
复制
// DateHelper.cpp
QString DateHelper::getWeekDay() {
    QDateTime currentDateTime = QDateTime::currentDateTime();
    int dayOfWeek = currentDateTime.date().dayOfWeek();
    QStringList weekDays;
    weekDays << "星期一" << "星期二" << "星期三" << "星期四"
             << "星期五" << "星期六" << "星期日";
    return weekDays[dayOfWeek - 1];
}
代码语言:javascript
复制
// main.qml
Text {
    text: dateHelper.getWeekDay()  // 调用 C++ 方法
}
对比总结

方面

JavaScript

C++

性能

解释执行

编译执行,快 10-100 倍

类型安全

运行时检查

编译时检查

代码复用

仅 QML 使用

可在多个地方复用

单元测试

困难

容易

调试

有限

完善的工具

维护性

对大型项目较难

结构清晰


6.7 扩展功能示例

使用英文星期
代码语言:javascript
复制
Text {
    text: dateHelper.getWeekDayEnglish()  // Monday
    font.pixelSize: 24
    color: "#87CEEB"
}
根据星期数字改变颜色
代码语言:javascript
复制
Text {
    id: weekDisplay
    text: dateHelper.getWeekDay()
    font.pixelSize: 28

    // 周末显示红色
    color: {
        var dayNum = dateHelper.getWeekDayNumber()
        return (dayNum === 6 || dayNum === 7) ? "#FF6B6B" : "#87CEEB"
    }
}
切换中英文显示
代码语言:javascript
复制
Rectangle {
    property bool showEnglish: false

    Text {
        text: showEnglish ?
              dateHelper.getWeekDayEnglish() :
              dateHelper.getWeekDay()
    }

    MouseArea {
        anchors.fill: parent
        onDoubleClicked: {
            parent.showEnglish = !parent.showEnglish
        }
    }
}

🎯 步骤七:添加装饰元素

现在我们已经实现了核心功能(时钟、日期、星期),让我们添加一些装饰元素让界面更精致。

7.1 添加分隔线

在星期和品牌信息之间添加装饰线:

代码语言:javascript
复制
Column {
    anchors.centerIn: parent
    spacing: 40

    // 时钟、日期、星期...

    // 装饰性分隔线
    Rectangle {
        width: 300
        height: 2
        color: "#00D4FF"
        radius: 1
        anchors.horizontalCenter: parent.horizontalCenter
        opacity: 0.6
    }

    // 品牌信息
    Text {
        text: "坚果派 × Qt for 鸿蒙"
        font.pixelSize: 24
        color: "#FFFFFF"
        opacity: 0.7
        anchors.horizontalCenter: parent.horizontalCenter
    }
}

装饰线技巧

  • width: 300:宽度
  • height: 2:高度(很细)
  • radius: 1:轻微圆角
  • opacity: 0.6:60% 透明度,更柔和

🔄 步骤八:实现 12/24 小时制切换

8.1 添加状态属性

在 Rectangle 中添加状态变量:

代码语言:javascript
复制
Rectangle {
    anchors.fill: parent

    // 状态标志
    property bool is24Hour: true

    // ... UI 组件
}

8.2 添加点击处理

代码语言:javascript
复制
Rectangle {
    anchors.fill: parent
    property bool is24Hour: true

    // ... UI 组件

    // 点击切换
    MouseArea {
        anchors.fill: parent
        onClicked: {
            // 切换状态
            parent.is24Hour = !parent.is24Hour

            var currentTime = new Date()
            if (parent.is24Hour) {
                // 24小时制:00:00:00
                timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")
            } else {
                // 12小时制:1:00:00 AM
                timeDisplay.text = Qt.formatTime(currentTime, "h:mm:ss AP")
            }
        }
    }
}

时间格式对比

格式

说明

示例

hh:mm:ss

24 小时制

13:30:45

h:mm:ss AP

12 小时制

1:30:45 PM

格式说明

  • hh:两位数小时(00-23)
  • h:一位或两位小时(1-12)
  • AP:AM/PM 标识

8.3 更新 Timer(完整版)

代码语言:javascript
复制
Timer {
    interval: 1000
    running: true
    repeat: true
    onTriggered: {
        var currentTime = new Date()

        // 根据当前模式更新时间
        if (parent.is24Hour) {
            timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")
        } else {
            timeDisplay.text = Qt.formatTime(currentTime, "h:mm:ss AP")
        }

        // 更新日期和星期
        dateDisplay.text = Qt.formatDate(currentTime, "yyyy年MM月dd日")
        weekDisplay.text = getWeekDay()
    }
}

📝 完整代码

项目文件结构

代码语言:javascript
复制
entry/src/main/cpp/
├── main.cpp           # C++ 入口文件,注册 DateHelper
├── main.qml           # QML 界面文件
├── DateHelper.h       # C++ 头文件,定义 DateHelper 类
├── DateHelper.cpp     # C++ 实现文件
├── CMakeLists.txt     # 构建配置文件
└── qml.qrc           # QML 资源文件

main.cpp(完整版)

代码语言:javascript
复制
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QSurfaceFormat>
#include <QQmlContext>
#include "DateHelper.h"

int main(int argc, char *argv[])
{
    // 配置 OpenGL ES 表面格式
    QSurfaceFormat format;
    format.setAlphaBufferSize(8);      // 确保 Alpha 通道位数
    format.setBlueBufferSize(8);       // 蓝色通道位数
    format.setGreenBufferSize(8);      // 绿色通道位数
    format.setRedBufferSize(8);        // 红色通道位数
    format.setDepthBufferSize(24);     // 深度缓冲区位数
    format.setStencilBufferSize(8);    // 模板缓冲区位数
    format.setRenderableType(QSurfaceFormat::OpenGLES); // 使用 OpenGL ES
    format.setVersion(3, 0);           // OpenGL ES 3.0
    QSurfaceFormat::setDefaultFormat(format);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // 创建 DateHelper 实例并将其暴露给 QML
    DateHelper dateHelper;
    engine.rootContext()->setContextProperty("dateHelper", &dateHelper);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

DateHelper.h(完整版)

代码语言:javascript
复制
// DateHelper.h
#ifndef DATEHELPER_H
#define DATEHELPER_H

#include <QObject>
#include <QDateTime>
#include <QString>

class DateHelper : public QObject
{
    Q_OBJECT

public:
    explicit DateHelper(QObject *parent = nullptr);

    // Q_INVOKABLE 使方法可以在 QML 中调用
    Q_INVOKABLE QString getWeekDay();
    Q_INVOKABLE QString getWeekDayEnglish();
    Q_INVOKABLE int getWeekDayNumber();

signals:

public slots:
};

#endif // DATEHELPER_H

DateHelper.cpp(完整版)

代码语言:javascript
复制
// DateHelper.cpp
#include "DateHelper.h"

DateHelper::DateHelper(QObject *parent)
    : QObject(parent)
{
}

// 获取中文星期
QString DateHelper::getWeekDay()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    int dayOfWeek = currentDateTime.date().dayOfWeek();

    QStringList weekDays;
    weekDays << "星期一" << "星期二" << "星期三" << "星期四"
             << "星期五" << "星期六" << "星期日";

    // Qt 的 dayOfWeek() 返回 1-7 (1=Monday, 7=Sunday)
    return weekDays[dayOfWeek - 1];
}

// 获取英文星期
QString DateHelper::getWeekDayEnglish()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    return currentDateTime.toString("dddd");
}

// 获取星期数字 (1-7)
int DateHelper::getWeekDayNumber()
{
    QDateTime currentDateTime = QDateTime::currentDateTime();
    return currentDateTime.date().dayOfWeek();
}

main.qml(完整版)

代码语言:javascript
复制
// main.qml - 时钟应用
import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 800
    height: 1200
    visible: true
    title: "Qt 时钟 for 鸿蒙"

    // 渐变背景
    Rectangle {
        anchors.fill: parent
        gradient: Gradient {
            GradientStop { position: 0.0; color: "#0F2027" }
            GradientStop { position: 0.5; color: "#203A43" }
            GradientStop { position: 1.0; color: "#2C5364" }
        }

        Column {
            anchors.centerIn: parent
            spacing: 40

            // 数字时钟显示
            Text {
                id: timeDisplay
                text: Qt.formatTime(new Date(), "hh:mm:ss")
                font.pixelSize: 120
                font.bold: true
                font.family: "Arial"
                color: "#FFFFFF"
                anchors.horizontalCenter: parent.horizontalCenter

                // 发光效果
                style: Text.Outline
                styleColor: "#00D4FF"
            }

            // 日期显示
            Column {
                spacing: 10
                anchors.horizontalCenter: parent.horizontalCenter

                Text {
                    id: dateDisplay
                    text: Qt.formatDate(new Date(), "yyyy年MM月dd日")
                    font.pixelSize: 36
                    color: "#B0E0E6"
                    anchors.horizontalCenter: parent.horizontalCenter
                }

                Text {
                    id: weekDisplay
                    text: dateHelper.getWeekDay()  // 使用 C++ 实现
                    font.pixelSize: 28
                    color: "#87CEEB"
                    anchors.horizontalCenter: parent.horizontalCenter
                }
            }

            // 装饰性分隔线
            Rectangle {
                width: 300
                height: 2
                color: "#00D4FF"
                radius: 1
                anchors.horizontalCenter: parent.horizontalCenter
                opacity: 0.6
            }

            // 品牌信息
            Text {
                text: "坚果派 × Qt for 鸿蒙"
                font.pixelSize: 24
                color: "#FFFFFF"
                opacity: 0.7
                anchors.horizontalCenter: parent.horizontalCenter
            }
        }

        // 定时器 - 每秒更新
        Timer {
            interval: 1000  // 1秒
            running: true
            repeat: true
            onTriggered: {
                var currentTime = new Date()
                timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")
                dateDisplay.text = Qt.formatDate(currentTime, "yyyy年MM月dd日")
                weekDisplay.text = dateHelper.getWeekDay()  // 使用 C++ 实现
            }
        }

        // 点击切换12/24小时制
        property bool is24Hour: true

        MouseArea {
            anchors.fill: parent
            onClicked: {
                parent.is24Hour = !parent.is24Hour
                var currentTime = new Date()
                if (parent.is24Hour) {
                    timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")
                } else {
                    timeDisplay.text = Qt.formatTime(currentTime, "h:mm:ss AP")
                }
            }
        }

        // 原来的 JavaScript getWeekDay() 函数已移至 C++ DateHelper 类
        // 现在通过 dateHelper.getWeekDay() 调用 C++ 实现
    }
}

CMakeLists.txt(完整版)

代码语言:javascript
复制
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(qtdemo)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

list(APPEND CMAKE_FIND_ROOT_PATH ${QT_PREFIX})
include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

find_package(QT NAMES Qt5 Qt6 REQUIRED COMPONENTS Core Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS
    Concurrent Gui Network Qml Quick QuickControls2
    Widgets QuickTemplates2 QmlWorkerScript)

add_library(entry SHARED
    main.cpp
    DateHelper.cpp
    DateHelper.h
    qml.qrc
)

target_link_libraries(entry PRIVATE
    Qt${QT_VERSION_MAJOR}::Concurrent
    Qt${QT_VERSION_MAJOR}::Core
    Qt${QT_VERSION_MAJOR}::Gui
    Qt${QT_VERSION_MAJOR}::Network
    Qt${QT_VERSION_MAJOR}::Qml
    Qt${QT_VERSION_MAJOR}::Quick
    Qt${QT_VERSION_MAJOR}::Widgets
    Qt${QT_VERSION_MAJOR}::QuickControls2
    Qt${QT_VERSION_MAJOR}::QuickTemplates2
    Qt${QT_VERSION_MAJOR}::QmlWorkerScript
    Qt${QT_VERSION_MAJOR}::QOpenHarmonyPlatformIntegrationPlugin
)

🎯 知识点总结

1. QML 布局

代码语言:javascript
复制
Column {
    anchors.centerIn: parent  // 居中对齐
    spacing: 40               // 子元素间距
}

2. 日期时间处理

QML/JavaScript 方式
代码语言:javascript
复制
// 获取当前时间
var now = new Date()

// 格式化时间
Qt.formatTime(now, "hh:mm:ss")

// 格式化日期
Qt.formatDate(now, "yyyy年MM月dd日")

// 获取星期(0-6)
now.getDay()
C++ 方式(推荐)
代码语言:javascript
复制
// 获取当前时间
QDateTime currentDateTime = QDateTime::currentDateTime();

// 获取星期(1-7)
int dayOfWeek = currentDateTime.date().dayOfWeek();

// 格式化
QString formatted = currentDateTime.toString("yyyy-MM-dd");

3. Timer 定时器

代码语言:javascript
复制
Timer {
    interval: 1000   // 间隔(毫秒)
    running: true    // 是否运行
    repeat: true     // 是否重复
    onTriggered: {}  // 触发回调
}

4. C++ 与 QML 集成

创建 C++ 类
代码语言:javascript
复制
class DateHelper : public QObject
{
    Q_OBJECT  // 必须添加

public:
    Q_INVOKABLE QString getWeekDay();  // 可在 QML 中调用
};
注册到 QML
代码语言:javascript
复制
// main.cpp
DateHelper dateHelper;
engine.rootContext()->setContextProperty("dateHelper", &dateHelper);
在 QML 中调用
代码语言:javascript
复制
Text {
    text: dateHelper.getWeekDay()  // 调用 C++ 方法
}

5. 属性绑定

代码语言:javascript
复制
property bool is24Hour: true
text: is24Hour ? "24小时制" : "12小时制"

6. CMake 配置要点

代码语言:javascript
复制
set(CMAKE_AUTOMOC ON)  # 自动运行 MOC

add_library(entry SHARED
    main.cpp
    DateHelper.cpp
    DateHelper.h
)

7. OpenGL ES 配置

代码语言:javascript
复制
QSurfaceFormat format;
format.setAlphaBufferSize(8);
format.setRenderableType(QSurfaceFormat::OpenGLES);
format.setVersion(3, 0);
QSurfaceFormat::setDefaultFormat(format);

🚀 扩展功能建议

1. 添加秒针动画

代码语言:javascript
复制
Text {
    id: timeDisplay

    Behavior on text {
        NumberAnimation {
            duration: 300
            easing.type: Easing.InOutQuad
        }
    }
}

2. 添加背景切换

代码语言:javascript
复制
property var backgrounds: [
    ["#0F2027", "#203A43", "#2C5364"],
    ["#834d9b", "#d04ed6", "#f2709c"],
    ["#000428", "#004e92", "#004e92"]
]

MouseArea {
    onDoubleClicked: {
        // 切换背景
    }
}

3. 添加闹钟功能

代码语言:javascript
复制
property string alarmTime: "07:00:00"

Timer {
    onTriggered: {
        if (timeDisplay.text === alarmTime) {
            // 触发闹钟
            console.log("闹钟响了!")
        }
    }
}

4. 添加世界时钟

代码语言:javascript
复制
function getTimeZone(offset) {
    var now = new Date()
    var utc = now.getTime() + (now.getTimezoneOffset() * 60000)
    var newTime = new Date(utc + (3600000 * offset))
    return Qt.formatTime(newTime, "hh:mm:ss")
}

Text {
    text: "纽约: " + getTimeZone(-5)
}

💻 适配鸿蒙 PC 平台

为什么要适配 PC?

鸿蒙 PC 是鸿蒙生态的重要组成部分,将应用适配到 PC 平台可以:

  • 📱 扩大用户群:覆盖桌面用户
  • 💼 办公场景:方便在电脑上查看时钟
  • 🖥️ 大屏体验:利用大屏幕展示更多信息
  • ⌨️ 键盘交互:支持键盘快捷键

PC 平台的特殊性

特性

手机/平板

鸿蒙 PC

窗口大小

固定全屏

可调整窗口

交互方式

触摸

鼠标+键盘

分辨率

较低

较高

多任务

有限

完全支持


🖥️ 步骤九:适配鸿蒙 PC

9.1 调整窗口大小

对于 PC 应用,我们需要设置合适的窗口尺寸:

代码语言:javascript
复制
Window {
    // 根据平台自动调整窗口大小
    width: Qt.platform.os === "ohos" ? 480 : 800
    height: Qt.platform.os === "ohos" ? 800 : 600
    visible: true
    title: "Qt 时钟 for 鸿蒙"

    // PC 特性:允许调整窗口大小
    minimumWidth: 400
    minimumHeight: 500
    maximumWidth: 1200
    maximumHeight: 900
}

配置说明

  • minimumWidth/Height:窗口最小尺寸
  • maximumWidth/Height:窗口最大尺寸
  • 用户可以拖拽边框调整窗口大小

9.2 响应式布局优化

使窗口大小变化时,界面自动适配:

代码语言:javascript
复制
Window {
    id: mainWindow

    Rectangle {
        anchors.fill: parent

        Column {
            anchors.centerIn: parent
            spacing: mainWindow.height * 0.03  // 根据窗口高度动态计算

            // 时钟显示 - 字体大小自适应
            Text {
                id: timeDisplay
                text: Qt.formatTime(new Date(), "hh:mm:ss")
                font.pixelSize: Math.min(mainWindow.width, mainWindow.height) * 0.15
                font.bold: true
                color: "#FFFFFF"
                anchors.horizontalCenter: parent.horizontalCenter
                style: Text.Outline
                styleColor: "#00D4FF"
            }

            // 日期显示 - 自适应字体
            Column {
                spacing: 10
                anchors.horizontalCenter: parent.horizontalCenter

                Text {
                    id: dateDisplay
                    text: Qt.formatDate(new Date(), "yyyy年MM月dd日")
                    font.pixelSize: mainWindow.width * 0.045
                    color: "#B0E0E6"
                    anchors.horizontalCenter: parent.horizontalCenter
                }

                Text {
                    id: weekDisplay
                    text: getWeekDay()
                    font.pixelSize: mainWindow.width * 0.035
                    color: "#87CEEB"
                    anchors.horizontalCenter: parent.horizontalCenter
                }
            }
        }
    }
}

响应式设计要点

  • 使用 mainWindow.width/height 动态计算尺寸
  • 字体大小根据窗口大小自动调整
  • 间距也使用百分比计算

9.3 添加键盘快捷键(PC 特性)

在 PC 上,添加键盘快捷键提升用户体验:

代码语言:javascript
复制
Window {
    id: mainWindow

    Rectangle {
        anchors.fill: parent

        // 启用键盘事件
        focus: true

        // 键盘事件处理
        Keys.onPressed: {
            if (event.key === Qt.Key_Space) {
                // 空格键:切换12/24小时制
                is24Hour = !is24Hour
                updateTimeDisplay()
                event.accepted = true
            }
            else if (event.key === Qt.Key_F11) {
                // F11:全屏切换
                if (mainWindow.visibility === Window.FullScreen) {
                    mainWindow.visibility = Window.Windowed
                } else {
                    mainWindow.visibility = Window.FullScreen
                }
                event.accepted = true
            }
            else if (event.key === Qt.Key_Escape) {
                // ESC:退出全屏
                if (mainWindow.visibility === Window.FullScreen) {
                    mainWindow.visibility = Window.Windowed
                }
                event.accepted = true
            }
            else if (event.key === Qt.Key_Q && event.modifiers & Qt.ControlModifier) {
                // Ctrl+Q:退出应用
                Qt.quit()
                event.accepted = true
            }
        }

        // 辅助函数:更新时间显示
        function updateTimeDisplay() {
            var currentTime = new Date()
            if (is24Hour) {
                timeDisplay.text = Qt.formatTime(currentTime, "hh:mm:ss")
            } else {
                timeDisplay.text = Qt.formatTime(currentTime, "h:mm:ss AP")
            }
        }
    }
}

快捷键列表

快捷键

功能

空格

切换 12/24 小时制

F11

全屏/窗口模式切换

ESC

退出全屏模式

Ctrl+Q

退出应用

9.4 添加右键菜单(PC 特性)

PC 用户习惯使用右键菜单:

代码语言:javascript
复制
Rectangle {
    anchors.fill: parent

    MouseArea {
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton | Qt.RightButton

        onClicked: {
            if (mouse.button === Qt.LeftButton) {
                // 左键:切换时间格式
                parent.is24Hour = !parent.is24Hour
                updateTimeDisplay()
            }
            else if (mouse.button === Qt.RightButton) {
                // 右键:显示上下文菜单
                contextMenu.popup()
            }
        }
    }

    // 上下文菜单
    Menu {
        id: contextMenu

        MenuItem {
            text: is24Hour ? "切换到12小时制" : "切换到24小时制"
            onTriggered: {
                is24Hour = !is24Hour
                updateTimeDisplay()
            }
        }

        MenuSeparator {}

        MenuItem {
            text: "全屏显示"
            onTriggered: {
                mainWindow.visibility = Window.FullScreen
            }
        }

        MenuItem {
            text: "关于"
            onTriggered: {
                aboutDialog.open()
            }
        }

        MenuSeparator {}

        MenuItem {
            text: "退出"
            onTriggered: {
                Qt.quit()
            }
        }
    }
}

注意:需要添加 import QtQuick.Controls 2.15 来使用 Menu 组件。

9.5 添加菜单栏(PC 标准)

为 PC 应用添加传统的菜单栏:

代码语言:javascript
复制
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    id: mainWindow
    width: 800
    height: 600
    visible: true
    title: "Qt 时钟 for 鸿蒙 PC"

    // 菜单栏
    menuBar: MenuBar {
        Menu {
            title: "文件(&F)"
            MenuItem {
                text: "退出(&Q)"
                shortcut: "Ctrl+Q"
                onTriggered: Qt.quit()
            }
        }

        Menu {
            title: "视图(&V)"
            MenuItem {
                text: "全屏(&F)"
                shortcut: "F11"
                checkable: true
                checked: mainWindow.visibility === Window.FullScreen
                onTriggered: {
                    if (checked) {
                        mainWindow.visibility = Window.FullScreen
                    } else {
                        mainWindow.visibility = Window.Windowed
                    }
                }
            }
            MenuSeparator {}
            MenuItem {
                text: is24Hour ? "12小时制(&1)" : "24小时制(&2)"
                shortcut: "Space"
                onTriggered: {
                    is24Hour = !is24Hour
                    updateTimeDisplay()
                }
            }
        }

        Menu {
            title: "帮助(&H)"
            MenuItem {
                text: "关于(&A)"
                onTriggered: {
                    aboutDialog.open()
                }
            }
        }
    }

    // 主内容区域
    Rectangle {
        anchors.fill: parent
        // ... 时钟界面代码
    }
}

9.6 PC 平台检测

根据不同平台显示不同的提示:

代码语言:javascript
复制
Text {
    text: {
        if (Qt.platform.os === "windows") {
            return "坚果派 × Qt for 鸿蒙 PC (Windows)"
        } else if (Qt.platform.os === "linux") {
            return "坚果派 × Qt for 鸿蒙 PC (Linux)"
        } else if (Qt.platform.os === "ohos") {
            return "坚果派 × Qt for 鸿蒙"
        } else {
            return "坚果派 × Qt"
        }
    }
    font.pixelSize: 24
    color: "#FFFFFF"
    opacity: 0.7
    anchors.horizontalCenter: parent.horizontalCenter
}

9.7 系统托盘支持(PC 特性)

在 PC 上添加系统托盘图标:

代码语言:javascript
复制
import QtQuick 2.15
import QtQuick.Window 2.15
import Qt.labs.platform 1.1

ApplicationWindow {
    id: mainWindow

    // 系统托盘图标
    SystemTrayIcon {
        id: systemTray
        visible: true
        icon.source: "qrc:/icons/clock.png"
        tooltip: "鸿蒙时钟"

        menu: Menu {
            MenuItem {
                text: "显示窗口"
                onTriggered: {
                    mainWindow.show()
                    mainWindow.raise()
                }
            }
            MenuItem {
                text: "隐藏窗口"
                onTriggered: mainWindow.hide()
            }
            MenuSeparator {}
            MenuItem {
                text: "退出"
                onTriggered: Qt.quit()
            }
        }

        onActivated: {
            if (reason === SystemTrayIcon.Trigger) {
                // 单击托盘图标
                if (mainWindow.visible) {
                    mainWindow.hide()
                } else {
                    mainWindow.show()
                    mainWindow.raise()
                }
            }
        }
    }
}

📋 PC 平台开发检查清单

在将应用发布到鸿蒙 PC 前,请确认:

  • [ ] 窗口大小设置合理(不要太小或太大)
  • [ ] 支持窗口大小调整(设置 min/max 尺寸)
  • [ ] 字体和控件大小自适应窗口
  • [ ] 添加键盘快捷键支持
  • [ ] 实现右键上下文菜单
  • [ ] 添加菜单栏(可选但推荐)
  • [ ] 测试全屏模式
  • [ ] 系统托盘功能(可选)
  • [ ] 适配深色/浅色主题
  • [ ] 在实际 PC 环境测试

🖥️ PC vs 移动端对比

代码差异

移动端版本
代码语言:javascript
复制
Window {
    width: 800
    height: 1200
    visible: true

    Rectangle {
        anchors.fill: parent
        // 固定布局
    }
}
PC 版本
代码语言:javascript
复制
ApplicationWindow {
    width: 800
    height: 600
    minimumWidth: 400
    minimumHeight: 500
    visible: true

    // 菜单栏
    menuBar: MenuBar { /* ... */ }

    Rectangle {
        anchors.fill: parent
        focus: true  // 接收键盘事件

        // 响应式布局
        Keys.onPressed: { /* 键盘处理 */ }
    }

    // 系统托盘
    SystemTrayIcon { /* ... */ }
}

功能对比

功能

移动端

PC 端

基础时钟显示

触摸交互

窗口调整

键盘快捷键

菜单栏

右键菜单

系统托盘

全屏模式

默认


🐛 常见问题

问题 1:时间不更新

症状:时钟显示静态时间

原因:Timer 未启动或 running 设置为 false

解决

代码语言:javascript
复制
Timer {
    running: true  // 确保为 true
    repeat: true   // 确保为 true
}

问题 2:日期格式显示错误

症状:日期显示为英文或格式不对

原因:格式字符串错误

解决

代码语言:javascript
复制
// 正确的中文格式
Qt.formatDate(new Date(), "yyyy年MM月dd日")

// 注意大小写
// MM - 月份(01-12)
// dd - 日期(01-31)

问题 3:星期显示不正确

症状:星期始终显示相同或显示错误

原因:getDay() 返回值使用错误

解决

代码语言:javascript
复制
// getDay() 返回 0-6
// 0 = 星期日,不是星期一!
var days = [
    "星期日",  // 0
    "星期一",  // 1
    // ...
]

问题 4:点击无响应

症状:点击屏幕无法切换 12/24 小时制

原因:MouseArea 被其他组件遮挡

解决

代码语言:javascript
复制
// 确保 MouseArea 在最后
Rectangle {
    // UI 组件...

    MouseArea {
        anchors.fill: parent
        onClicked: { /* ... */ }
    }
}

📊 性能优化

1. 减少不必要的更新

代码语言:javascript
复制
Timer {
    onTriggered: {
        var currentTime = new Date()
        var newTimeText = Qt.formatTime(currentTime, "hh:mm:ss")

        // 只在时间改变时更新
        if (timeDisplay.text !== newTimeText) {
            timeDisplay.text = newTimeText
        }
    }
}

2. 使用缓存

代码语言:javascript
复制
property string cachedDate: ""

Timer {
    onTriggered: {
        var newDate = Qt.formatDate(new Date(), "yyyy年MM月dd日")

        // 日期通常不会每秒改变
        if (cachedDate !== newDate) {
            cachedDate = newDate
            dateDisplay.text = newDate
        }
    }
}

🎨 设计建议

颜色选择

  • 对比度:确保文字与背景有足够对比度
  • 和谐性:使用相近色系保持视觉统一
  • 可读性:时间数字使用高亮色,便于快速识别

字体大小

  • 时钟:120px(主要信息)
  • 日期:36px(次要信息)
  • 星期:28px(辅助信息)
  • 品牌:24px(装饰信息)

间距设置

  • 主要组件间距:40px
  • 相关信息间距:10px
  • 留白:充足的留白让界面更清爽

💡 最佳实践

✅ 应该做的

使用 Timer 进行实时更新

代码语言:javascript
复制
Timer { interval: 1000; running: true; repeat: true }

为组件设置有意义的 id

代码语言:javascript
复制
Text { id: timeDisplay }  // 清晰明了

使用函数封装重复逻辑

代码语言:javascript
复制
function getWeekDay() { /* ... */ }

添加用户交互反馈

代码语言:javascript
复制
MouseArea {
    onClicked: { /* 提供视觉或音频反馈 */ }
}

使用 property 管理状态

代码语言:javascript
复制
property bool is24Hour: true

❌ 不应该做的

硬编码所有值

代码语言:javascript
复制
// 不好
Text { text: "19:30:45" }

// 好
Text { text: Qt.formatTime(new Date(), "hh:mm:ss") }

在 Timer 中执行复杂计算

代码语言:javascript
复制
// Timer 频繁触发,避免复杂操作
onTriggered: {
    // 简单的更新操作
}

忘记清理资源

代码语言:javascript
复制
Component.onDestruction: {
    // 如有需要,清理定时器等资源
}

📚 参考资源

Qt 官方文档

QML 相关
  • Qt QML Timer[1] - 定时器组件文档
  • Qt Global Object[2] - Qt 全局对象
  • QML Date Functions[3] - 日期函数
C++ 相关
  • Q_INVOKABLE Macro[4] - Q_INVOKABLE 宏文档
  • QQmlContext[5] - QML 上下文
  • QDateTime[6] - 日期时间类
  • Qt MOC[7] - 元对象编译器
集成相关
  • Integrating QML and C++[8] - C++ 和 QML 集成指南
  • Exposing C++ Objects to QML[9] - 将 C++ 对象暴露给 QML

🎉 总结

通过本教程,我们从零开始构建了一个功能完整的时钟应用,涵盖了:

  1. 界面设计:渐变背景、布局结构
  2. 实时更新:Timer 组件的使用
  3. 时间处理:日期时间格式化
  4. 交互功能:12/24 小时制切换
  5. C++ 集成:DateHelper 类实现和 QML 集成
  6. OpenGL ES 配置:图形渲染优化
  7. 视觉效果:文字发光、装饰元素
  8. 跨平台适配:支持手机、平板、PC

核心技能

QML 技能
  • QML 布局和组件使用
  • Timer 定时器应用
  • 用户交互处理(MouseArea)
  • 状态管理(property)
  • 视觉效果设计
C++ 技能
  • Qt 元对象系统(Q_OBJECT)
  • Q_INVOKABLE 方法定义
  • QDateTime 日期时间处理
  • QML 上下文属性注册
  • CMake 构建配置
集成技能
  • C++ 与 QML 数据交互
  • 性能优化考虑
  • 代码架构设计
  • 跨平台开发

下一步学习方向

移动端功能扩展

  • 添加闹钟功能
  • 实现秒表和倒计时
  • 支持多时区显示
  • 添加主题切换
  • 数据持久化

PC 端功能扩展

  • 桌面挂件模式
  • 多时区时钟并排显示
  • 番茄钟功能
  • 开机自启动
  • 快捷键自定义
  • 窗口置顶功能

跨平台特性

  • 云同步设置
  • 多设备协同
  • 统一的数据格式
  • 自适应不同设备

继续探索,创造更多精彩的应用!🚀

🌟 鸿蒙全场景开发

本教程的时钟应用展示了鸿蒙全场景开发的特点:

代码语言:javascript
复制
一套代码 → 多端运行

📱 手机端  ←→  📱 平板端  ←→  💻 PC端
   触摸         触摸+鼠标      鼠标+键盘
   竖屏         横屏/竖屏      大屏

这正是鸿蒙生态的优势所在!

文档版本:v1.0 最后更新:2025-11-06 作者:坚果派 难度等级:⭐⭐⭐ (中级) 预计学习时间:2-3 小时 标签QtQMLHarmonyOS时钟实战教程

参考资料

[1]

Qt QML Timer: https://doc.qt.io/qt-5/qml-qtqml-timer.html

[2]

Qt Global Object: https://doc.qt.io/qt-5/qml-qtqml-qt.html

[3]

QML Date Functions: https://doc.qt.io/qt-5/qml-date.html

[4]

Q_INVOKABLE Macro: https://doc.qt.io/qt-5/qobject.html#Q_INVOKABLE

[5]

QQmlContext: https://doc.qt.io/qt-5/qqmlcontext.html

[6]

QDateTime: https://doc.qt.io/qt-5/qdatetime.html

[7]

Qt MOC: https://doc.qt.io/qt-5/moc.html

[8]

Integrating QML and C++: https://doc.qt.io/qt-5/qtqml-cppintegration-overview.html

[9]

Exposing C++ Objects to QML: https://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大前端之旅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 📱 最终效果
  • 📚 前置知识
    • 需要了解的技术
      • 必须掌握
      • 建议了解
    • 开发环境
    • 平台支持
  • 🚀 步骤一:创建项目基础结构
    • 1.1 创建 main.qml 文件
    • 1.2 运行验证
  • 🎨 步骤二:设计渐变背景
    • 2.1 添加渐变效果
  • ⏰ 步骤三:实现时钟显示
    • 3.1 添加时钟文本组件
      • 基础属性
      • Qt.formatTime() 函数
      • 发光效果
    • 3.2 运行验证
  • 🔄 步骤四:实现实时更新
    • 4.1 添加 Timer 组件
    • 4.2 运行验证
  • 📅 步骤五:添加日期显示
    • 5.1 创建布局结构
    • 5.2 更新 Timer
  • 📆 步骤六:使用 C++ 实现星期显示
    • 为什么使用 C++?
    • 6.1 创建 DateHelper 头文件
      • Q_OBJECT 宏
      • Q_INVOKABLE 宏
      • 三个方法说明
    • 6.2 实现 DateHelper 类
      • QDateTime vs JavaScript Date
      • QStringList 操作
      • toString() 格式化
    • 6.3 更新 CMakeLists.txt
    • 6.4 在 main.cpp 中注册 C++ 对象
      • setContextProperty()
      • 生命周期管理
    • 6.5 在 QML 中调用 C++ 方法
      • 调用 C++ 方法
      • 更新 Timer
    • 6.6 JavaScript vs C++ 实现对比
      • JavaScript 实现(旧方法)
      • C++ 实现(推荐)
      • 对比总结
    • 6.7 扩展功能示例
      • 使用英文星期
      • 根据星期数字改变颜色
      • 切换中英文显示
  • 🎯 步骤七:添加装饰元素
    • 7.1 添加分隔线
  • 🔄 步骤八:实现 12/24 小时制切换
    • 8.1 添加状态属性
    • 8.2 添加点击处理
    • 8.3 更新 Timer(完整版)
  • 📝 完整代码
    • 项目文件结构
    • main.cpp(完整版)
    • DateHelper.h(完整版)
    • DateHelper.cpp(完整版)
    • main.qml(完整版)
    • CMakeLists.txt(完整版)
  • 🎯 知识点总结
    • 1. QML 布局
    • 2. 日期时间处理
      • QML/JavaScript 方式
      • C++ 方式(推荐)
    • 3. Timer 定时器
    • 4. C++ 与 QML 集成
      • 创建 C++ 类
      • 注册到 QML
      • 在 QML 中调用
    • 5. 属性绑定
    • 6. CMake 配置要点
    • 7. OpenGL ES 配置
  • 🚀 扩展功能建议
    • 1. 添加秒针动画
    • 2. 添加背景切换
    • 3. 添加闹钟功能
    • 4. 添加世界时钟
  • 💻 适配鸿蒙 PC 平台
    • 为什么要适配 PC?
    • PC 平台的特殊性
  • 🖥️ 步骤九:适配鸿蒙 PC
    • 9.1 调整窗口大小
    • 9.2 响应式布局优化
    • 9.3 添加键盘快捷键(PC 特性)
    • 9.4 添加右键菜单(PC 特性)
    • 9.5 添加菜单栏(PC 标准)
    • 9.6 PC 平台检测
    • 9.7 系统托盘支持(PC 特性)
  • 📋 PC 平台开发检查清单
  • 🖥️ PC vs 移动端对比
    • 代码差异
      • 移动端版本
      • PC 版本
    • 功能对比
  • 🐛 常见问题
    • 问题 1:时间不更新
    • 问题 2:日期格式显示错误
    • 问题 3:星期显示不正确
    • 问题 4:点击无响应
  • 📊 性能优化
    • 1. 减少不必要的更新
    • 2. 使用缓存
  • 🎨 设计建议
    • 颜色选择
    • 字体大小
    • 间距设置
  • 💡 最佳实践
    • ✅ 应该做的
    • ❌ 不应该做的
  • 📚 参考资源
    • Qt 官方文档
      • QML 相关
      • C++ 相关
      • 集成相关
  • 🎉 总结
    • 核心技能
      • QML 技能
      • C++ 技能
      • 集成技能
    • 下一步学习方向
    • 🌟 鸿蒙全场景开发
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档