QT开发鸿蒙PC应用:第一个Qt Widget应用入门

背景与概述

随着OpenHarmony生态向PC端扩展,基于QT框架开发桌面级应用成为开发者关注的新方向。Qt Widgets作为QT框架中成熟的桌面UI模块,为开发传统PC应用提供了丰富的控件和稳定的API支持。本文将详细介绍如何在OpenHarmony PC环境下创建第一个Qt Widgets应用。

请注意:本文使用的Qt for OpenHarmony SDK由OpenHarmony SIG社区基于Qt 5.15独立开发和维护,非Qt官方版本。

Qt Widgets在OpenHarmony PC端的优势

Qt Widgets模块经过多年发展,拥有完善的桌面应用开发组件库,特别适合开发生产力工具、办公软件等传统PC应用。在OpenHarmony PC环境中,Qt Widgets能够:

  1. 快速移植现有应用:大量基于Qt Widgets的桌面应用可相对容易地迁移到OpenHarmony PC平台
  2. 高性能渲染:Widgets采用原生绘制,在PC硬件上能够实现流畅的界面响应
  3. 丰富的控件库:提供按钮、表格、树形视图等完整的桌面级UI组件
  4. 成熟的开发模式:支持可视化设计(Qt Designer)与代码开发相结合

环境搭建与配置

本文假设您已完成基础环境搭建,包括:

  • 安装DevEco Studio 5.0.5及以上版本
  • 下载并配置Qt for OpenHarmony SDK
  • 了解OpenHarmony应用开发基础

如未完成,请参考前文《QT开发鸿蒙移动应用:环境搭建及第一个HelloWorld程序》中的环境搭建部分。

文档适用范围

  • OpenHarmony API 15 (5.0.3)及以上版本
  • Qt for OpenHarmony (基于Qt 5.15)
  • 目标设备:OpenHarmony PC设备

创建Qt Widgets工程

1. 新建OpenHarmony工程

  1. 打开DevEco Studio,选择"Create Project"
  2. 选择"Native C++"模板
  3. 配置工程信息:
    • Project Name: QtWidgetDemo
    • Bundle Name: com.example.qtwidgetdemo
    • Device Type: 选择"PC"(如无PC选项,可选择"Tablet"并后续调整配置)
    • Compile SDK: 选择API 17或更高版本
    • Model: 选择"Stage"

2. 修改为OpenHarmony工程

修改工程级build-profile.json5文件:

json 复制代码
"products": [
  {
    "name": "default",
    "signingConfig": "default",
    "compileSdkVersion": 17,
    "targetSdkVersion": 17,
    "compatibleSdkVersion": 17,
    // ... 其他配置
  }
]

点击"Sync Now"同步工程。

3. 工程配置调整

3.1 修改Native编译配置

在模块级build-profile.json5中配置Qt SDK路径和架构:

json 复制代码
"externalNativeOptions": {
  "path": "./src/main/cpp/CMakeLists.txt",
  "arguments": "-DQT_PREFIX=/path/to/your/QtForOpenHarmony",
  "abiFilters": ["arm64-v8a"] // PC设备通常使用64位ARM或x86架构
}

注意:根据实际PC设备架构调整abiFilters,可能为["arm64-v8a"]["x86_64"]

3.2 拷贝依赖文件
  1. 拷贝ets文件 :将Qt SDK下的openharmony/qtbase目录内容复制到src/main/ets目录
  2. 拷贝库文件 :将Qt SDK下的plugins/platforms/libplugins_platforms_qopenharmony.so拷贝到libs/对应架构目录下
  3. PC特有配置:如SDK提供PC专用库,需一并拷贝
3.3 配置UIAbility

module.json5中配置PC应用入口:

json 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "deviceTypes": ["pc"], // 指定为PC设备
    "abilities": [
      {
        "name": "EntryAbility",
        "launchType": "specified",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": ["entity.system.desktop"],
            "actions": ["ohos.want.action.desktop"]
          }
        ]
      }
    ]
  }
}

编写Qt Widgets应用

1. 清理与准备

  1. 移除src/main/cpp目录下默认生成的napi_init.cpp文件
  2. 创建以下文件:
    • main.cpp:应用入口
    • mainwindow.h:主窗口头文件
    • mainwindow.cpp:主窗口实现
    • mainwindow.ui:主窗口UI设计文件

2. 关键文件代码

只需依赖跟widget相关的库,QML的库则不需要了。

CMakeLists.txt

cmake 复制代码
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(qtWidgetdemo)

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

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED 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 Widgets)

add_library(entry SHARED
    main.cpp
    mainwindow.cpp
    mainwindow.h
    mainwindow.ui
)

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}::Widgets
    ${QT_PREFIX}/plugins/platforms/libplugins_platforms_qopenharmony.so
)

main.cpp

cpp 复制代码
#include <QApplication>
#include <QSurfaceFormat>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    // 配置OpenGL ES表面格式(PC端也可使用OpenGL)
    QSurfaceFormat format;
    format.setAlphaBufferSize(8);
    format.setBlueBufferSize(8);
    format.setGreenBufferSize(8);
    format.setRedBufferSize(8);
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setRenderableType(QSurfaceFormat::OpenGLES);
    format.setVersion(3, 0);
    QSurfaceFormat::setDefaultFormat(format);
    
    QApplication app(argc, argv);
    
    // 设置应用信息
    app.setApplicationName("Qt Widgets for OpenHarmony PC");
    app.setOrganizationName("OpenHarmony SIG");
    
    MainWindow window;
    window.show();
    
    return app.exec();
}

mainwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void onHelloButtonClicked();
    void onExitButtonClicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
    // 设置窗口属性
    setWindowTitle("Qt Widgets on OpenHarmony PC");
    resize(800, 600);
    
    // 连接信号槽
    connect(ui->helloButton, &QPushButton::clicked, 
            this, &MainWindow::onHelloButtonClicked);
    connect(ui->exitButton, &QPushButton::clicked,
            this, &MainWindow::onExitButtonClicked);
    
    // 设置状态栏消息
    statusBar()->showMessage("Ready - Qt Widgets Application");
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onHelloButtonClicked()
{
    QMessageBox::information(this, 
        "Hello OpenHarmony PC",
        "Welcome to Qt Widgets on OpenHarmony PC Platform!\n\n"
        "This is a traditional desktop application built with Qt Widgets.");
    
    // 更新状态栏
    statusBar()->showMessage("Hello button clicked at " + 
                            QTime::currentTime().toString());
    
    // 在文本编辑框中添加消息
    ui->textEdit->append("Hello OpenHarmony PC - " + 
                        QDateTime::currentDateTime().toString());
}

void MainWindow::onExitButtonClicked()
{
    QMessageBox::StandardButton reply;
    reply = QMessageBox::question(this, "Exit Application",
            "Are you sure you want to exit?",
            QMessageBox::Yes | QMessageBox::No);
    
    if (reply == QMessageBox::Yes) {
        qDebug() << "Application exiting...";
        QApplication::quit();
    }
}

mainwindow.ui (XML格式 - 可通过Qt Designer创建)

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Qt Widgets on OpenHarmony PC</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QLabel" name="titleLabel">
      <property name="text">
       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:18pt; font-weight:700;&quot;&gt;Qt Widgets Application&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:14pt;&quot;&gt;OpenHarmony PC Platform&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
      <property name="alignment">
       <set>Qt::AlignCenter</set>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QTextEdit" name="textEdit">
      <property name="placeholderText">
       <string>Application log will appear here...</string>
      </property>
     </widget>
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <item>
       <widget class="QPushButton" name="helloButton">
        <property name="text">
         <string>Say Hello</string>
        </property>
        <property name="minimumSize">
         <size>
          <width>120</width>
          <height>40</height>
         </size>
        </property>
       </widget>
      </item>
      <item>
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
      <item>
       <widget class="QPushButton" name="exitButton">
        <property name="text">
         <string>Exit</string>
        </property>
        <property name="minimumSize">
         <size>
          <width>120</width>
          <height>40</height>
         </size>
        </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

Widget界面,可以通过电脑桌面Qt环境自带的QtCreator这个工具来编辑。

3. 界面设计说明

上述UI文件创建了一个典型的桌面应用窗口,包含:

  1. 标题标签:显示应用名称和平台信息
  2. 文本编辑框:用于显示应用日志和消息
  3. 功能按钮
    • "Say Hello"按钮:显示欢迎消息并更新日志
    • "Exit"按钮:退出应用(带确认对话框)
  4. 状态栏:显示应用状态信息

构建与运行

1. 构建应用

  1. 在DevEco Studio中,点击"Build" → "Build HAP(s)"
  2. 等待构建完成,确保无编译错误

2. 运行应用

由于目前OpenHarmony PC模拟器可能尚未普及,建议在以下环境运行:

方案一:真实PC设备

  1. 准备已刷入OpenHarmony PC版的设备
  2. 通过USB连接设备
  3. 在DevEco Studio中选择目标设备
  4. 点击运行按钮,应用将自动安装并启动

方案二:远程调试

  1. 配置PC设备的远程调试选项
  2. 在DevEco Studio中配置远程连接
  3. 部署并运行应用

方案三:兼容模式运行

  1. 如无PC设备,可尝试在平板设备上运行
  2. 调整窗口大小和布局以适应不同屏幕

3. 应用效果

应用启动后,将显示一个标准的桌面窗口,包含:

  • 标题栏(可最小化/最大化/关闭)
  • 中央内容区域
  • 底部状态栏
  • 完整的菜单栏、工具栏(可根据需要添加)

调试与优化

1. 常见问题解决

  1. 库文件缺失:确保所有Qt库文件已正确拷贝到libs目录
  2. 架构不匹配:确认设备架构与abiFilters配置一致
  3. 权限问题 :在module.json5中申请必要的PC应用权限

2. 性能优化建议

  1. 懒加载控件:大型应用可考虑动态加载UI组件
  2. 资源管理:合理管理图片、字体等资源
  3. 事件处理:优化耗时操作,避免阻塞UI线程

3. PC特有功能扩展

cpp 复制代码
// 示例:添加PC特有的菜单栏
void MainWindow::createMenus()
{
    // 文件菜单
    QMenu *fileMenu = menuBar()->addMenu("File");
    QAction *newAction = fileMenu->addAction("New");
    QAction *openAction = fileMenu->addAction("Open");
    fileMenu->addSeparator();
    QAction *exitAction = fileMenu->addAction("Exit");
    
    // 帮助菜单
    QMenu *helpMenu = menuBar()->addMenu("Help");
    QAction *aboutAction = helpMenu->addAction("About");
    
    // 连接信号槽
    connect(exitAction, &QAction::triggered, this, &MainWindow::close);
    connect(aboutAction, &QAction::triggered, this, &MainWindow::showAboutDialog);
}

未来展望

Qt Widgets在OpenHarmony PC平台的应用开发具有重要价值:

  1. 企业级应用迁移:大量现有Qt桌面应用可平滑迁移至OpenHarmony PC
  2. 生产力工具开发:利用Qt Widgets丰富控件库开发办公、设计等专业软件
  3. 混合开发模式:结合Qt Quick和Qt Widgets,兼顾传统界面与现代UI需求
  4. 生态建设:推动OpenHarmony PC应用生态的快速成熟

随着OpenHarmony PC生态的完善,Qt Widgets将成为连接传统桌面应用与新一代操作系统的重要桥梁,为开发者提供高效、可靠的PC应用开发解决方案。


开发提示:本文示例为基础演示,实际PC应用开发需考虑多窗口管理、系统集成、快捷键支持等桌面应用特性。建议参考Qt官方文档和OpenHarmony PC开发指南进行深入开发。

相关推荐
AI人工智能+电脑小能手3 小时前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
yyuuuzz3 小时前
独立站的技术基础与常见运维问题
大数据·运维·服务器·网络·数据库·aws
键盘上的猫头鹰6 小时前
【MySQL 教程(八)】索引、事务、用户管理、导入导出与分页查询
数据库·python·mysql
Royzst6 小时前
数据库知识点
数据库
花椒技术6 小时前
复杂直播业务做 RN 跨端,我们最后保留了哪些 Native 边界
react native·react.js·harmonyos
雪的季节7 小时前
企业级 Qt 全功能项目
开发语言·数据库·qt
宋浮檀s7 小时前
应急响应——Web漏洞:命令执行+SSRF+弱口令
运维·数据库·sql·网络安全·oracle·应急响应
yurenpai(27届找实习中)8 小时前
redis_点评(21.好友关注——关注、取关功能实现;共同关注功能实现)
数据库·redis·缓存
Rick19938 小时前
索引的排序和分组
数据库·mysql
爱莉希雅&&&8 小时前
zabbix快速搭建和使用
android·linux·数据库·zabbix·监控