Qt + HarmonyOS 每日早报应用开发实战

📱 项目简介

本文将详细介绍如何使用 Qt 框架在 HarmonyOS 平台上开发一款每日早报应用。该应用通过网络请求获取每日新闻数据,并以美观的界面展示给用户,是学习 Qt + HarmonyOS 开发的绝佳实战案例。

项目地址: https://gitcode.com/nutpi/QtDailyMorningPost

效果:

image-20251109081935086

✨ 主要功能

  • 📰 获取并展示每日早报新闻(15条)
  • 🔄 支持手动刷新功能
  • 💬 显示每日微语
  • 🎨 现代化的 Material Design 风格界面
  • ⚡ 异步网络请求,不阻塞UI
  • 🛡️ 完善的错误处理机制

🛠️ 技术栈

  • 开发框架: Qt 5.x for HarmonyOS
  • 编程语言: C++ 17 / QML
  • 网络库: Qt Network (QNetworkAccessManager)
  • 数据格式: JSON (Qt JSON)
  • 界面: QML + Qt Quick Controls 2
  • 构建工具: CMake
  • 目标平台: HarmonyOS (OpenHarmony)

🏗️ 项目架构

qtdemo-1/
├── entry/src/main/
│   ├── cpp/
│   │   ├── main.cpp              # 应用入口
│   │   ├── main.qml              # 主界面
│   │   ├── newsmanager.h         # 新闻管理器头文件
│   │   ├── newsmanager.cpp       # 新闻管理器实现
│   │   └── CMakeLists.txt        # 构建配置
│   ├── module.json5              # 模块配置(权限)
│   └── resources/                # 资源文件

📝 核心功能实现

1. NewsManager - 网络请求与数据管理

NewsManager 是整个应用的核心类,负责网络请求、数据解析和状态管理。

1.1 类定义 (newsmanager.h)
class NewsManager : public QObject
{
    Q_OBJECT
    // 定义属性,可在QML中直接访问
    Q_PROPERTY(QString date READ date NOTIFY dateChanged)
    Q_PROPERTY(QStringList newsList READ newsList NOTIFY newsListChanged)
    Q_PROPERTY(QString weiyu READ weiyu NOTIFY weiyuChanged)
    Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
    Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)

public:
    explicit NewsManager(QObject *parent = nullptr);
    
    // Getter 方法
    QString date() const { return m_date; }
    QStringList newsList() const { return m_newsList; }
    QString weiyu() const { return m_weiyu; }
    bool loading() const { return m_loading; }
    QString errorMessage() const { return m_errorMessage; }

public slots:
    void fetchNews();  // 获取新闻的槽函数,QML可调用

signals:
    // 信号,数据变化时通知QML更新界面
    void dateChanged();
    void newsListChanged();
    void weiyuChanged();
    void loadingChanged();
    void errorMessageChanged();

private slots:
    void onNetworkReply(QNetworkReply *reply);

private:
    void parseJsonResponse(const QByteArray &data);
    
    QNetworkAccessManager *m_networkManager;
    QString m_date;
    QStringList m_newsList;
    QString m_weiyu;
    bool m_loading;
    QString m_errorMessage;
};

设计要点

  • 使用 Q_PROPERTY 将 C++ 属性暴露给 QML
  • 使用信号-槽机制实现数据变化通知
  • 所有需要在 QML 中调用的方法都声明为 public slots
1.2 网络请求实现 (newsmanager.cpp)
void NewsManager::fetchNews()
{
    setLoading(true);
    setErrorMessage("");
    
    // 使用HTTP协议(Qt for HarmonyOS 不支持HTTPS)
    QUrl url("http://v3.alapi.cn/api/zaobao");
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, 
                     "application/x-www-form-urlencoded");
    
    // 设置10秒超时
    request.setTransferTimeout(10000);
    
    // 构建POST参数
    QUrlQuery params;
    params.addQueryItem("token", "ycd0krwbhl5v2w6iafblj94y5vzqdj");
    params.addQueryItem("format", "json");
    
    QByteArray postData = params.toString(QUrl::FullyEncoded).toUtf8();
    
    qDebug() << "发送早报请求到:" << url.toString();
    m_networkManager->post(request, postData);
}

技术要点

  • Qt for HarmonyOS 不支持 SSL,必须使用 HTTP 协议
  • 使用 POST 方法发送请求
  • 通过 QUrlQuery 构建表单数据
  • 设置合理的超时时间避免长时间等待
1.3 数据解析
void NewsManager::parseJsonResponse(const QByteArray &data)
{
    QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
    QJsonObject root = doc.object();
    
    if (root["code"].toInt() != 200) {
        setErrorMessage("API错误: " + root["msg"].toString());
        return;
    }
    
    QJsonObject dataObj = root["data"].toObject();
    
    // 解析日期
    m_date = dataObj["date"].toString();
    emit dateChanged();
    
    // 解析新闻列表
    QJsonArray newsArray = dataObj["news"].toArray();
    m_newsList.clear();
    for (int i = 0; i < newsArray.size(); ++i) {
        m_newsList.append(newsArray[i].toString());
    }
    emit newsListChanged();
    
    // 解析微语
    m_weiyu = dataObj["weiyu"].toString();
    emit weiyuChanged();
}

关键点

  • 使用 Qt JSON 模块解析 JSON 数据
  • 每次数据更新后发送相应的信号通知 QML
  • 完善的错误处理

2. QML 界面实现

2.1 主窗口布局
Window {
    width: 800
    height: 1200
    visible: true
    title: "每日早报 - Qt for 鸿蒙"

    Rectangle {
        anchors.fill: parent
        gradient: Gradient {
            GradientStop { position: 0.0; color: "#e3f2fd" }
            GradientStop { position: 1.0; color: "#bbdefb" }
        }
        
        // 标题栏
        Rectangle { ... }
        
        // 刷新按钮
        Button { ... }
        
        // 新闻列表
        ScrollView { ... }
        
        // 微语区域
        Rectangle { ... }
    }
}
2.2 新闻列表实现
ListView {
    id: newsListView
    width: parent.width
    spacing: 15
    
    model: newsManager.newsList  // 直接绑定C++数据
    
    delegate: Rectangle {
        width: newsListView.width
        height: Math.max(newsText.implicitHeight + 40, 60)
        color: "#ffffff"
        radius: 12
        border.color: "#90caf9"
        border.width: 2
        
        Text {
            id: newsText
            text: modelData
            font.pixelSize: 26
            color: "#212121"
            anchors.fill: parent
            anchors.margins: 20
            wrapMode: Text.Wrap
            lineHeight: 1.4
        }
    }
}

设计亮点

  • 使用 ListView 实现高性能滚动列表
  • 卡片式设计,每条新闻独立显示
  • 自动计算高度适应内容
  • Material Design 配色方案
2.3 交互功能
Button {
    text: newsManager.loading ? "加载中..." : "🔄 刷新"
    enabled: !newsManager.loading
    
    onClicked: {
        newsManager.fetchNews()  // 调用C++方法
    }
}

// 自动加载
Component.onCompleted: {
    newsManager.fetchNews()
}

3. C++ 与 QML 数据绑定

main.cpp 中注册 C++ 对象到 QML 上下文:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    
    // 创建NewsManager实例
    NewsManager newsManager;
    
    // 注册到QML上下文,名称为"newsManager"
    engine.rootContext()->setContextProperty("newsManager", &newsManager);
    
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

数据流程

  1. QML 调用 newsManager.fetchNews()
  2. C++ 发起网络请求
  3. 数据返回后解析并更新成员变量
  4. 发送 newsListChanged() 等信号
  5. QML 界面自动更新显示

🔧 配置与权限

1. CMakeLists.txt 配置

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

# 链接Qt Network模块
target_link_libraries(entry PRIVATE 
    Qt${QT_VERSION_MAJOR}::Network
    Qt${QT_VERSION_MAJOR}::Qml
    Qt${QT_VERSION_MAJOR}::Quick
    # ... 其他模块
)

2. 网络权限配置

module.json5 中添加网络权限:

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:internet_permission_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      }
    ]
  }
}

string.json 中添加权限说明:

{
  "string": [
    {
      "name": "internet_permission_reason",
      "value": "需要网络权限来获取每日早报数据"
    }
  ]
}

🐛 问题与解决方案

问题1: Protocol ‘https’ is unknown

原因: Qt for HarmonyOS 版本未编译 SSL/TLS 支持

解决方案: 将 API 请求协议从 HTTPS 改为 HTTP

// 错误:QUrl url("https://v3.alapi.cn/api/zaobao");
// 正确:
QUrl url("http://v3.alapi.cn/api/zaobao");

问题2: Host not found

原因: 应用缺少网络权限

解决方案: 在 module.json5 中添加 ohos.permission.INTERNET 权限

问题3: 新闻列表只显示边框不显示文字

原因:

  • ListView delegate 高度计算问题
  • layer.effect 在某些 Qt 版本有兼容性问题

解决方案:

// 使用 implicitHeight 计算高度
height: Math.max(newsText.implicitHeight + 40, 60)

// 移除可能有问题的 layer.effect
// layer.enabled: true  // 删除此行

问题4: 编译错误 - QSslError incomplete type

原因: 引入了不支持的 SSL 相关头文件

解决方案: 从代码中移除所有 SSL 相关的引用

// 删除:#include <QSslSocket>
// 删除:#include <QSslError>
// 删除:#include <QSslConfiguration>

🎯 优化技巧

1. 性能优化

  • 使用 ListView 而不是 Repeater,支持虚拟化滚动
  • 网络请求使用异步方式,不阻塞 UI 线程
  • 合理设置超时时间避免无限等待

2. 用户体验优化

  • 添加加载状态指示器
  • 显示友好的错误信息
  • 支持下拉刷新
  • 自动加载初始数据

3. 调试技巧

添加详细的日志输出:

qDebug() << "收到的原始数据:" << data;
qDebug() << "API返回code:" << code;
qDebug() << "新闻数组大小:" << newsArray.size();

📊 效果展示

应用运行效果:

  • ✅ 顶部蓝色标题栏显示"每日早报"和日期
  • ✅ 中间区域滚动显示15条新闻,每条新闻在白色卡片中
  • ✅ 底部橙色区域显示每日微语
  • ✅ 点击刷新按钮可重新获取数据
  • ✅ 加载过程中显示"加载中…"状态

🎓 学习要点

通过这个项目,你将学到:

  1. Qt Network 编程: HTTP POST 请求、数据解析
  2. QML 界面开发: ListView、ScrollView、Material Design
  3. C++ 与 QML 交互: Q_PROPERTY、信号-槽、上下文注册
  4. HarmonyOS 开发: 权限配置、模块管理
  5. JSON 数据处理: Qt JSON API 的使用
  6. 异步编程: 网络请求的异步处理
  7. 错误处理: 网络错误、解析错误的处理机制

🚀 扩展方向

基于现有功能,你可以继续扩展:

  1. 添加缓存机制: 使用 SQLite 存储历史数据
  2. 支持图片显示: 显示早报头图
  3. 分享功能: 分享新闻到社交平台
  4. 收藏功能: 收藏感兴趣的新闻
  5. 历史记录: 查看往期早报
  6. 推送通知: 每天定时推送早报
  7. 主题切换: 支持深色模式
  8. 字体设置: 可调节字体大小

📚 参考资源

💡 总结

本文通过一个完整的每日早报应用案例,展示了如何使用 Qt 框架在 HarmonyOS 平台上开发网络应用。从网络请求、数据解析到界面展示,涵盖了移动应用开发的核心技能。

项目的关键技术点包括:

  • Qt Network 模块的使用
  • C++ 与 QML 的数据绑定
  • Qt JSON API 的应用
  • HarmonyOS 权限配置
  • Material Design 界面设计

希望这个案例能帮助你快速上手 Qt + HarmonyOS 开发!


作者: 坚果派
日期: 2025-11-09
项目地址: https://gitcode.com/nutpi/QtDailyMorningPost
许可证: MIT

如果觉得这篇文章对你有帮助,欢迎 Star ⭐ 支持!

Logo

赋能鸿蒙PC开发者,共建全场景原生生态,共享一次开发多端部署创新价值。

更多推荐