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开发指南进行深入开发。

相关推荐
Vic101012 小时前
【无标题】
java·数据库·分布式
l1t2 小时前
sqlite递归查询指定搜索顺序的方法
数据库·sql·sqlite·dfs·递归·cte
深蓝海拓2 小时前
PySide6从0开始学习的笔记(十八) MVC(Model-View-Controller)模式的图形渲染体系
笔记·python·qt·学习·pyqt
盛世宏博北京2 小时前
守护千年文脉:图书馆古籍库房自动化环境治理(温湿度 + 消毒)技术方案
服务器·数据库·自动化·图书馆温湿度监控
「光与松果」2 小时前
Mongodb 日常维护命令集
数据库·mongodb
哥哥还在IT中2 小时前
etcd内存占用高如何排查
数据库·etcd
Web极客码2 小时前
使用phpMyAdmin轻松操作WordPress数据库
数据库·oracle
啥都不懂的小小白2 小时前
MVCC深度解析:MySQL如何实现高效无阻塞的并发读写
数据库·mysql·mvcc
程序员根根2 小时前
MySQL 事务全解析:从 ACID 特性到实战落地(部门 - 员工场景)
数据库·后端