文章目录
背景
Qt4自2005年发布已为成千上万的应用程序甚至桌面操作系统、移动操作系统提供了稳定、可靠的开发框架。
计算机用户的使用模式近年发生了变化,用户正在从传统PC转向笔记本电脑或智能手机。传统PC被越来越多的触摸屏设备取代,计算机的用户体验模型也在跟随改变。在这之前Windows UI占据了我们的世界,但现在我们会花更多的时间使用其它的UI语言开发便携式设备用户界面。
Qt4的设计用于满足开发者在主流桌面操作系统上有一套表现一致的窗口组件可以使用。如今Qt的使用者面临了新的问题,他们需要提供可触碰交互的用户界面以满足软件界面需求,并在主流桌面操作系统和移动操作系统上实现这些界面。
从 Qt4.7
版本开始引进了 Qt Quick
,它让Qt的使用者可以用简单的元素对象创建一套界面组件,并通过组合界面组件的方式来完成软件界面需求。
QML 作为一种灵活高效的界面开发语言已经越来越得到业界的认可。使用 QML
和 JavaScript
创建用户界面,后端使用 C++
处理数据。前后端的分离让前端开发人员可以快速迭代并专注于用户界面开发,后端的 C++
开发人员则专注于软件的稳定性、高性能和扩展能力。
谈一谈为我什么学QtQuick
-
桌面应用式微,移动端、嵌入式端崛起,且传统桌面开发正在被
Chromium V8 + 大前端
的模式所侵占。这方面最最具代表性的应数 VSCode。不信自己检查一下自己电脑上还是多少软件是采用
.Net原生开发
、还有多少应用是采用Qt
这类的跨平台框架、还有多少应用是采用Chromium V8 + 大前端
。 -
这是一个看脸的时代:传统Qt没有好看的
开源ui库
,而默认样式风格较为远古,调qss
也并不是一件然人愉快的事情!QtQuick
所用qml
可以视为是JavaScript
的超集,存在享受前端喷井式爆发红利的可能性。之所以这样说是因为我发现了一个VOFA+ 的项目,它采用
QtQuick
开发,颠覆了我对Qt应用的认知。(原谅我见得少) -
在现代的软件开发中有一个内在的冲突,用户界面的改变速度远远高于我们的后端服务。在传统的技术中我们开发的前端需要与后端保持相同的步调。当一个项目在开发时用户想要改变用户界面,或者在一个项目中开发一个用户界面的想法就会引发这个冲突。
很不幸,由于前期需求不明确,我目前所作的项目正在饱受该问题的困扰。
Qt Quick
提供了一个类似HTML
声明语言的环境应用程序作为你的用户界面前端(the front-end
),在你的后端使用本地的c++
代码。能较好的解决这个给问题。 -
一点小算盘:在 Qt - UI数据双向绑定简易实现 中使用的数据UI双向绑定实现得过于粗暴,且绑定得数据类型必须是是
Hint
,基本没有实际可用意义。qml
有属性绑定,或许我可以参考点什么。 -
必须对新事物保持敏感度。
环境搭建
Qt 安装
从 Qt5.15(最新LTS)
开始,对于开源版本已经不提供已经制作好的离线exe安装包,我们只能选择:
-
自行编译安装
-
在线联网安装
安装包下载地址:
安装过程略,可参考:
VS2019 安装
这里我选择的是 VS2019 Professional版(听说它比较小)
安装完成后我们还需要补充工作负载:
Qt Visual Studio Tools
若想在VS中导入Qt工程,需要安装 Qt Visual Studio Tools
。
可至 扩展->管理扩展 中添加:
安装完成后还需要进行配置:
导入工程后出现以下警告直接忽略即可,我们需要手动打开工程文件:
Hello World
安装完成后,老规矩,我们从 Hello World
开始。
新建空白工程:
.pro
QT += quick
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
TRANSLATIONS += \
empty_zh_CN.ts
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
与我们以往的 Project
不同的是:
-
QT += quick
-
RESOURCES += qml.qrc
-
QML_IMPORT_PATH =
-
QML_DESIGNER_IMPORT_PATH =
-
Default rules for deployment
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine> // include a QML engine
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // High DPI Displays(added in Qt 5.6)
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml")); // loading QML file
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
注意:这里使用了之前没见过的类,QQmlApplicationEngine
。engine
加载 main.qml
,如果加载失败那么程序退出,然后开启了事件循环,仅此而已。
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Text {
text: "<b>Hello</b> <i>World!</i>"
}
}
看着就知道什么意思了…
我随手加了个 Text
以显示 “Hello World!”