Qt for HarmonyOS/weather 天气应用项目

项目概述

weather是一款基于Qt/QML开发的HarmonyOS天气应用,旨在提供轻量、稳定、可扩展的天气信息服务。该应用实现了城市搜索/收藏、当前天气展示、小时预报等核心功能,同时具备适配弱网环境、跨分辨率自适应等特性。

项目地址:https://gitcode.com/szkygc/weather

技术栈概览

  • 平台: HarmonyOS (鸿蒙)
  • 前端框架: Qt/QML
  • 后端语言: C++
  • 数据获取: QNetworkAccessManager
  • 数据解析: QJsonDocument
  • UI组件: QtQuick.Controls, Layouts, GraphicalEffects
  • 数据源: APIHZ聚合接口、OpenWeather兼容结构

核心功能特性

  • 🏙️ 城市搜索:支持城市搜索和快速查询
  • 🌡️ 当前天气:展示温度、天气现象、体感温度、湿度、风向风速等详细信息
  • 🎨 自适应UI:支持不同分辨率设备,全局缩放适配
  • 🔄 容错机制:多节点自动重试、数据格式兼容、图标失败兜底
  • 📱 优质体验:渐变背景、半透明卡片、阴影圆角等视觉效果

架构设计

项目结构

复制代码
weather/
├── entry/src/main/cpp/
│   ├── main.qml         # 应用主界面
│   ├── main.cpp         # 应用入口
│   ├── weatherdatafetcher.cpp/.h # 数据获取与解析
│   └── CMakeLists.txt   # 构建配置
└── docs/                # 项目文档

模块划分

  • 界面层main.qml负责所有UI展示和用户交互
  • 数据层WeatherDataFetcher处理网络请求、数据解析和错误处理

核心技术实现

1. 数据获取与处理

cpp 复制代码
// 天气数据获取类的关键属性
explicit WeatherDataFetcher(QObject *parent = nullptr);

Q_PROPERTY(QString cityName READ cityName NOTIFY cityNameChanged)
Q_PROPERTY(QString temperature READ temperature NOTIFY temperatureChanged)
Q_PROPERTY(QString weatherCondition READ weatherCondition NOTIFY weatherConditionChanged)
Q_PROPERTY(QString humidity READ humidity NOTIFY humidityChanged)
Q_PROPERTY(QString windSpeed READ windSpeed NOTIFY windSpeedChanged)
Q_PROPERTY(QString pressure READ pressure NOTIFY pressureChanged)
Q_PROPERTY(QString visibility READ visibility NOTIFY visibilityChanged)
Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
Q_PROPERTY(QString apiHzId READ apiHzId WRITE setApiHzId NOTIFY apiHzIdChanged)
Q_PROPERTY(QString apiHzKey READ apiHzKey WRITE setApiHzKey NOTIFY apiHzKeyChanged)
Q_PROPERTY(QVariantList hourly READ hourly NOTIFY hourlyChanged)
Q_PROPERTY(QString icon READ icon NOTIFY iconChanged)
Q_PROPERTY(QString feelsLike READ feelsLike NOTIFY feelsLikeChanged)
Q_PROPERTY(QString windDirection READ windDirection NOTIFY windDirectionChanged)
Q_PROPERTY(QString windScale READ windScale NOTIFY windScaleChanged)
Q_PROPERTY(QString precipitation READ precipitation NOTIFY precipitationChanged)
Q_PROPERTY(QString updateTime READ updateTime NOTIFY updateTimeChanged)

// 关键方法和信号
Q_INVOKABLE void fetchWeather(const QString &city);
Q_INVOKABLE void fetchWeatherByLocation(double latitude, double longitude);
Q_INVOKABLE void setApiHzId(const QString &id);
Q_INVOKABLE void setApiHzKey(const QString &key);
signals:
    void weatherFetched(bool success, const QString &error = "");
    void hourlyChanged();

2. 网络请求与容错机制

cpp 复制代码
// 多节点候选与自动重试
void WeatherDataFetcher::issueApiHzRequest()
{
    if (m_apiHzBases.isEmpty()) {
        prepareApiHzCandidates();
    }
    const int idx = qBound(0, m_apiHzTryIndex, m_apiHzBases.size() - 1);
    const QString base = m_apiHzBases.at(idx);
    const QString url = buildApiHzUrl(base, m_lastShengParam, m_lastPlaceParam);
    QNetworkRequest req;
    req.setUrl(QUrl(url));
    req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    req.setAttribute(QNetworkRequest::User, QVariant("apihz"));
    m_networkManager->get(req);
}

3. 图标资源规范化处理

cpp 复制代码
static inline QString normalizeIconUrl(const QString &raw)
{
    if (raw.isEmpty()) return QString();
    if (raw.startsWith(QStringLiteral("https://"))) {
        const QUrl u(raw);
        const QString host = u.host();
        QString fileName = QFileInfo(u.path()).fileName();
        if (!fileName.isEmpty() && host.contains(QStringLiteral("rescdn.apihz.cn"))) {
            if (fileName.endsWith(QStringLiteral(".png"), Qt::CaseInsensitive)) {
                fileName.chop(4);
                fileName += QStringLiteral(".gif");
            }
            return QStringLiteral("http://cn.apihz.cn/skin/tianqi/icon/") + fileName;
        }
        return raw;
    }
    if (raw.startsWith(QStringLiteral("http://"))) return raw;
    return QStringLiteral("http://cn.apihz.cn/skin/tianqi/icon/") + raw;
}

4. QML界面实现

城市标题与搜索/收藏功能
qml 复制代码
// 城市信息 + 搜索/收藏按钮
RowLayout {
    Layout.alignment: Qt.AlignHCenter
    Layout.topMargin: 20 * root.uiScale
    spacing: 10 * root.uiScale
    Text { text: weatherFetcher.cityName || "北京"; font.pixelSize: 36 * root.uiScale; font.bold: true; color: "white" }
    Button {
        text: "🔍"
        background: Rectangle { radius: 20 * root.uiScale; color: "#4DFFFFFF" }
        onClicked: searchDialog.open()
    }
    // 收藏按钮已移除
}
自适应详情网格布局
qml 复制代码
GridLayout {
    id: gridCards
    Layout.fillWidth: true
    columnSpacing: 12 * root.uiScale
    rowSpacing: 12 * root.uiScale
    readonly property int targetCols: 3
    readonly property real cardMinWidth: 160 * root.uiScale
    readonly property int computedCols: Math.max(1, Math.min(targetCols, Math.floor(width / (cardMinWidth + columnSpacing))))
    columns: computedCols
}

// 小时预报组件已移除

项目配置与构建

主要配置文件

  1. CMakeLists.txt:定义Qt依赖、构建参数和输出路径
  2. module.json5:配置应用入口和能力
  3. main.cpp:初始化Qt应用并加载QML

开发与运行步骤

  1. 环境配置:安装Qt for HarmonyOS的SDK和工具链
  2. API配置 :在 main.qml中设置 apiHzIdapiHzKey
  3. 构建运行:编译并部署到HarmonyOS设备
  4. 调试监控 :关注 weatherFetched信号和控制台日志

关键问题解决方案

1. HTTPS兼容性问题

  • 问题:Qt for HarmonyOS环境下HTTPS协议支持受限
  • 解决方案 :使用HTTP协议替代,通过 normalizeIconUrl函数处理URL转换

2. 界面自适应

  • 问题:不同设备分辨率下界面布局需要适配
  • 解决方案 :实现全局 uiScale缩放因子,基于短边800为基准进行计算

3. 网络容错

  • 问题:弱网环境下API请求可能失败
  • 解决方案:实现多节点候选列表,失败自动切换重试

4. 数据格式兼容

  • 问题:API返回格式可能变化或不一致
  • 解决方案:优先解析APIHZ结构,失败时尝试解析OpenWeather结构

性能优化

  1. 图标缓存Image组件启用 cache: true提高加载效率
  2. 异步加载 :使用 asynchronous: true避免阻塞UI线程
  3. 网格自适应:动态计算列数以适应不同屏幕宽度
  4. 内存管理:合理处理网络请求和JSON解析,避免内存泄漏

调试技巧

  1. 信号监控 :监听 weatherFetched信号和 loading状态
  2. 日志分析:观察原始JSON数据和解析过程
  3. UI调试 :通过调整 uiScale因子快速验证不同尺寸显示效果
  4. 错误模拟:可以通过修改API凭证或网络设置来测试错误处理机制

项目效果展示

  • ✅ 城市搜索功能正常工作
  • ✅ 当前天气信息完整展示
  • ✅ 界面自适应不同分辨率设备
  • ✅ 在弱网环境下具备容错能力
  • ✅ 图标加载失败时有兜底处理

学习要点

  1. Qt与HarmonyOS集成:掌握Qt框架在HarmonyOS平台的部署和使用
  2. C++与QML交互:通过属性、信号槽机制实现数据绑定
  3. 跨平台适配:实现界面自适应和网络兼容
  4. 容错设计:构建健壮的网络请求和数据处理流程
  5. 简化架构:移除不必要组件,保持代码简洁高效

未来扩展方向

  1. 功能增强:增加15天预报、AQI空气质量、生活指数等功能
  2. 用户体验:引入定位服务、多语言支持、主题切换
  3. 技术优化:实现数据缓存、离线模式、更丰富的天气动效
  4. 架构升级:模块化服务抽象,支持更多数据源

总结

weather项目成功验证了Qt/QML在HarmonyOS平台上的可行性和实用性。通过多节点重试、格式容错、资源规范化等策略,应用能够在复杂网络环境下提供稳定的用户体验。项目架构清晰,代码组织合理,具备良好的可扩展性,可以作为学习和二次开发的优秀模板。

日期: 2025年11月

相关推荐
云帆小二3 小时前
从开发语言出发如何选择学习考试系统
开发语言·学习
光泽雨3 小时前
python学习基础
开发语言·数据库·python
百***06014 小时前
python爬虫——爬取全年天气数据并做可视化分析
开发语言·爬虫·python
IT考试认证4 小时前
华为AI认证 H13-323 HCIP-AI Solution Architect 题库
人工智能·华为·题库·hcip-ai·h13-323
jghhh014 小时前
基于幅度的和差测角程序
开发语言·matlab
fruge4 小时前
自制浏览器插件:实现网页内容高亮、自动整理收藏夹功能
开发语言·前端·javascript
爱笑的眼睛115 小时前
ArkTS接口与泛型在HarmonyOS应用开发中的深度应用
华为·harmonyos
曹牧5 小时前
Java中处理URL转义并下载PDF文件
java·开发语言·pdf
未来之窗软件服务5 小时前
幽冥大陆(二十二)dark语言智慧农业电子秤读取——东方仙盟炼气期
开发语言·windows·golang·东方仙盟·东方仙盟sdk
逐步前行5 小时前
C项目--羊了个羊(两关全)--含源码
c语言·开发语言