跨平台GUI开发 - Qt
阅读量
0
阅读人次
0
开发环境搭建
下载Qt Online Installer,如果Installer(安装或更新)下载速度太慢,可以选择镜像源:
.\qt-unified-windows-x64-4.6.0-online.exe --mirror https://mirrors.tuna.tsinghua.edu.cn/qt/
.\MaintenanceTool.exe --mirror https://mirrors.tuna.tsinghua.edu.cn/qt/
注意:Windows下安装时,需要以管理员权限启动,否则安装Windows Debugger以及Runtime组件时,会一直提示无权限安装失败。
Ubuntu下首先需要安装一下软件包:
sudo apt-get install libgl1-mesa-dev
QML模块化开发
假设我有这么一个模块:
Fluent
├── CMakeLists.txt
├── Rectangle.cpp
├── Rectangle.h
└── qml
└── Text.qml
那么 CMakeLists.txt
应该这么 写:
cmake_minimum_required(VERSION 3.29) # 目前发现 CMake 低版本不能正常使用 qt_add_qml_module()
add_library(Fluent
# 其他源文件
)
qt_add_qml_module(Fluent
URI Fluent
VERSION 1.0
PLUGIN_TARGET FluentPlugin # 如果不指定,那么默认就是 TARGET+"plugin",即 Fluentplugin
SOURCES
Rectangle.h Rectangle.cpp
QML_FILES
qml/Text.qml
)
这样会生成两个静态库文件,以Windows下为例,一个是 Fluent.lib
,一个是 Fluentplugin.lib
。所以我们在链接应用程序时,指定这个两个静态库,即可成功使用。
如果是生成动态库文件,则可以将 Fluentplugin.dll
拷贝值可执行应用程序,即可加载。(正确性待确定)
无边框
在 Qt 开发,对于一些较真的 UI 设计师,经常会设计一下需要自定义标题栏的需求。Qt 并没有提供自定义窗口标题栏的实现,更不用说跨平台了。这是因为 Windows 使用 DWM(Desktop Window Manager)管理窗口程序的移动,缩放,标题栏,边框效果。Linux 上窗口管理系统因为发行系统多样化,其则更加多样化了。
在网上也有很多人尝试自己封装跨平台的 Qt 无边框窗口类,例如 QWindowKit,这是中国程序员发起的,我看也有很多人用,不过大部分人都在提 issue
,我也拉下来试用了一下,发现其确实在不同Windows版本之前,不用Qt版本之间,多台显示器(还可能分辨率不一致,DPI不一致)会遇到各种各样的问题,表现不一致甚至带来不能使用的BUG。但不管怎样,它在尝试统一封装跨平台。
最后,就只能自己针对每种平台的桌面窗口管理系统(DWM),进行特定平台的代码开发了。这里可以提一下 FluentUI,他使用 Qt QML 实现了 Fluent 设计风格的 Qt 组件。最开始它也是使用的 QWindowKit
作为无边框实现,但是看 commit
应该是 QWindowKit
作者对该项目做了一些迁移改动,FluentUI
就自己实现了 Windows 下的无边框窗口实现,并自定义标题栏。顺便提一下这个库的控件样式很棒,作者也是中国人。
善用 QVariantList 和 QVariantMap
当我们希望将 C++ 中的数据结构传递到 QML 中时,一般通常做的方式是,使用 Q_OBJECT
、Q_GADGET
实现一个数据结构,好让 QML 能够认识它,但是这样呢,比较麻烦。在一个稍微大一点的项目中,肯定有很多数据结构需要交换。
这个时候使用 QVariantList 和 QVariantMap 可以省去重新 实现一个类的繁琐工作。
class Manager : public QObject {
Q_OBJECT
public:
QVariantList availableUsbVideoCameras() const {
QVariantList ret;
auto devices = cameras();
for (auto &device : devices) {
QVariantMap item;
item.insert("name", device.name);
item.insert("path", device.path);
ret << item;
}
return ret;
}
};
ComboBox {
textRole: "name"
model: Manager.availableUsbVideoCameras()
}
多语言支持 Qt Linguist
Qt for Android
在搭建 Qt for Android 开发环境时,我们可以设置环境变量ANDROID_SDK_HOME
为D:\Android
。这样,一些文件,例如AVD,就不会默认存放在C盘,而放在D:\Android
文件夹下,在这里,我也将Android SDK和NDK放在了这个文件夹,以便以后统一管理。
Qt Creator第一次在编译Android程序时,会提示需要下载Gradle:
Generating Android Package
Input file: E:/Projects/untitled1-Qt_6_5_0_Clang_arm64_v8a-Debug/android-appuntitled1-deployment-settings.json
Output directory: E:/Projects/untitled1-Qt_6_5_0_Clang_arm64_v8a-Debug/android-build/
Application binary: appuntitled
Android build platform: android-31
Install to device: No
Downloading https://services.gradle.org/distributions/gradle-8.0-bin.zip
但是通常由于国内GFW的问题,会导致下载失败。我们可以手动下载上述打印的Gradle压缩包,然后不解压直接放在 C:\Users\你的账户\.gradle\wrapper\dists\gradle-8.0-bin\ca5e32bp14vu59qr306oxotwh
下,这个目录可能会随着版本变化而变化(但是 C:\Users\你的账户\.gradle\wrapper\dists\gradle-x.x-bin
是不会发生改变的),需要注意。
打包
windeployqt FactoryTool.exe
dumpbin /DEPENDENTS FactoryTool.exe
脱坑经验
插件调试
Qt为了跨平台,使用了plugin插件的方式对各个库进行集成,在实际部署的时候,我们编写的程序运行时可能缺少插件依赖的库或对应库的版本不对,使得程序崩溃且不输出相关错误信息,这时我们需要设置环境变量:
export QT_DEBUG_PLUGINS=1
就可以看到Qt程序加载各个插件的过程,看到详细的报错信息。