目前c/s架构的应用开发已经有了足够多的选择,其中跨平台的开发也非常多.比如Dart的Flutter,C++的Qt,.Net的MAUI等等,不过其中坑不是外行能一眼看透的,尤其是微软相关的UI技术栈分支实在多,跨平台相关能力不明(微软这方面的文档感觉还是有点乱),学习资料不够充足,而Qt并不开源,但是最近我看到其官网又更新了一波技术,感觉很亮眼,咱们来看看.
目前跨平台的解决方案还是琳琅满目,但其中比较成熟的开发效率不低的,网上教程多的又成了凤毛麟角.让我说的话,有Flutter,.Net MAUI以及Qt等等
Flutter就不多提了,我是最推荐这个的.
.Net相关项目在微软操持下,生不如死.最成熟的是WPF本身不支持跨平台,此外的Avalonia,Uno等跨平台并不是微软首推. 微软目前首推MAUI与Blazor,后者是Web框架,此外还有UWP的继任者WinUI3目前也不成熟(其目的应该是占据WPF的部分市场).聊聊MAUI、WinUI3和WPF的优势及劣势 - 杜文龙 - 博客园 (cnblogs.com)
此外还有移动端跨平台的React Native,Jetpack Compose(Compose Multiplatform)等等,桌面应用还有Electron,Tauri(目前也能在移动端使用)等,国内生态下还有微信小程序,Uniapp,Taro等.
Jetpack Compose 是一款新型工具包,旨在帮助简化界面开发。该工具包将响应式编程模型与简洁易用的 Kotlin 编程语言相结合,并采用完全声明式的代码编写方式,让您可以通过调用一系列函数来描述界面,这些函数会将数据转换为界面层次结构。当底层数据发生变化时,框架会自动重新执行这些函数,为您更新界面层次结构。简单来说,包括Flutter,这些都是使用代码声明UI的,而.Net下许多UI框架使用xaml,这与之前的安卓开发类似.
上面说了这么多,做技术选型来个总结的话,当然首先需要顾及团队人员,最好结合工期和团队技术栈选择.如果是个人开发者,由于目前Flutter对web和桌面支持还是不太成熟,我个人其实想推荐.Net的技术,或者你也可以考虑Electron做桌面(强调软件性能或者容错性考虑WPF,Qt等),移动端用Flutter或React Native(Compose目前跨平台也不太成熟,如果只考虑安卓可以试试)
而今天要谈到的Qt,在工业领域用得多,感觉还是因为历史沉淀.这几天看了Qt官网,其推出了Design Studio软件,Qt Creator貌似也支持了AI辅助编码,说明还是跟上了潮流,而Qt6的优势就是跟Qt quick更好结合了.目前下载Qt也不像之前那么麻烦,现在用一个unified-downloader联网下载以及后续更新就行了.
新的Qt
Qt主要还是在桌面、嵌入式多,但其实移动端也可以,相信其跨平台能力.Qt6与Qt5基本可以无缝转换.
Qt 6 is highly compatible with Qt 5. Developers of Qt 5 applications can move seamlessly to Qt 6 while retaining the applications’ functionality.
Qt目前提供了设计,开发,测试和优化的工具,主要使用前两者即可.
对于UI设计
如果想要在移动端或者需要丝滑的动画,那就用Qt Quick.可以使用Qt Design Studio辅助设计.
1
2
3
4
5import QtQuick
Rectangle {
id: page
anchors.fill: parent
color: "#ffffff"}
使用qml描述界面1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48ListModel {
id: todayTasksListModel
}
ListModel {
id: thisWeekTasksListModel
}
ListModel {
id: laterTasksListModel
}
Column {
id: column
anchors.fill: parent
spacing: 14
TasksList {
id: todayTasks
width: column.width
maxHeight: 180
listModel: todayTasksListModel
headerText: qsTr("Today")
tasksCount: todayTasksListModel.count
}
TasksList {
id: thisWeekTasks
width: column.width
maxHeight: column.height - y - 60
listModel: thisWeekTasksListModel
headerText: qsTr("This week")
tasksCount: thisWeekTasksListModel.count
}
TasksList {
id: laterTasks
width: column.width
maxHeight: column.height - y
listModel: laterTasksListModel
headerText: qsTr("Later")
tasksCount: laterTasksListModel.count
}
}
我在使用的时候感觉很像安卓的compose或者WPF的xaml开发,也是声明式,Flutter也是声明式,这可能就是趋势吧.类似js通过findelementById再到React,Vue的声明式UI.
使用QtWidget
1
2
3
4
5
6
7
8
9
10
11
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Notepad w;
w.show();
return a.exec();
}
使用QtWidget是传统开发方式,这里就不赘述了.
目前我在Qt官网以及开发工具上找到了一堆tutorial,可惜目前没多少时间学习,可以预见的是,虽然Qt在互联网以及开源软件领域基本没什么市场占有率(目前被Web技术占着,要么就是Flutter或者.Net),但是在使用c++比较多的工业领域或是使用Python进行Qt开发应该是一个技术上不错的选择了.比如下面代码就是用python执行qml.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47import sys
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
QML = """
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Window {
width: 300
height: 200
visible: true
title: "Hello World"
readonly property list<string> texts: ["Hallo Welt", "Hei maailma",
"Hola Mundo", "Привет мир"]
function setText() {
var i = Math.round(Math.random() * 3)
text.text = texts[i]
}
ColumnLayout {
anchors.fill: parent
Text {
id: text
text: "Hello World"
Layout.alignment: Qt.AlignHCenter
}
Button {
text: "Click me"
Layout.alignment: Qt.AlignHCenter
onClicked: setText()
}
}
}
"""
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.loadData(QML.encode('utf-8'))
if not engine.rootObjects():
sys.exit(-1)
exit_code = app.exec()
del engine
sys.exit(exit_code)
下面是常见的用python写qtwidget1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32import sys
import random
from PySide6 import QtCore, QtWidgets, QtGui
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.hello = ["Hallo Welt", "Hei maailma", "Hola Mundo", "Привет мир"]
self.button = QtWidgets.QPushButton("Click me!")
self.text = QtWidgets.QLabel("Hello World",
alignment=QtCore.Qt.AlignCenter)
self.layout = QtWidgets.QVBoxLayout(self)
self.layout.addWidget(self.text)
self.layout.addWidget(self.button)
self.button.clicked.connect(self.magic)
def magic(self):
self.text.setText(random.choice(self.hello))
if __name__ == "__main__":
app = QtWidgets.QApplication([])
widget = MyWidget()
widget.resize(800, 600)
widget.show()
sys.exit(app.exec())
目前QtWidget与Qt quick没有绝对优劣,官网也是推荐在使用动画和移动端触摸时使用qml,事实上这两者也可以结合使用. 而安卓方面Compose已经成了趋势,但传统xml开发也需要掌握用来维护旧项目以及新项目缺少的组件.
其他技术可以看看这篇文章总结得不错桌面软件开发框架大赏 - 知乎 (zhihu.com)