关于 Qt
关于 Qt
我始终认为 Qt 是 C++ 中一个没太多技术含量的方向。写 Qt 的人实际上写的是 Qt 而不是 C++,就像写 Spring 的人也只是在写 Spring 而不是 Java.
这些年随着 Web 技术的兴起和 Flutter 突然横插一脚转变成神仙打架,客户端行业已经不能更萎靡了。在我看来 Qt,或者说至少 C++ Qt,在未来唯一能够坐稳的赛道就是工控机客户端领域。因为那些电脑性能破烂不堪,有些设备是连图形界面都没有,一个精简版安卓都刷不上的。这种设备显然不太可能上 Electron/Flutter,只能在那些有自带图形引擎的 GUI 框架里找,结果找来找去确实只有 Qt 能打,所以也只能用 Qt.
其实工控机领域这些图形界面的功能很简单,比起现在前端的活不知道简单多少,就仅仅是做个把数据展示出来的活,大部分情况下啥交互也不用做。虽然 C++ 复杂度很高,而且 Qt 自己其实也有不少很复杂的东西,但这些大部分给工控机做展示界面的 Qt 编程工作其实是没啥技术含量的。
为啥用 C++?一是做这行的多数不是正经计算机专业毕业的,多半是工科背景,大学里只教 C/C++,Java 都很少教,HTML/CSS/JS 这些东西更是完全陌生,用 C++ 最熟——虽然他们其实也不怎么懂 C++,就是当作 C with cout and class 来用,但 Qt 恰好只要他们会这些。二是该领域的传感器厂商基本给的接口都是 C/C++ 的接口,例子也是用 C 或 C++ 写的,可以直接看文档,抄起来方便。如果用其他语言,自己需要做适配,这行中有比较大一部分程序员搞不定。而且这行又不像 Web 那边,其实做的都是一套东西,资料很多,每个硬件厂给的 API 都不一样,你只有厂子给的文档可以看,没别的资料能查。
行业这番现状就导致了大家普遍认为工控机的 UI 界面丑的不行。其实完全可以做得不丑,WPS 也是 Qt 写的,也可以做得好看。关键是很多给工控机用 Qt 写界面的程序员 layout 也不用,不加弹簧 spacer,QSS 一概不知,很多软件界面都是大小写死的,只在一个特定尺寸的屏幕上能看。
其实 Qt 有点类似于一个原始的 Flutter,组件和布局是耦合进代码里的,而样式美化则用 QSS。相比起 HTML/CSS/JS 那套,Qt 在代码里干了 HTML、JS 和一部分 CSS(布局)的活,然后使用 QSS(CSS 的一种变体)干了 CSS 剩下的活;相比起 Flutter,Qt 在代码里干了大部分活,但一些不涉及界面布局的美化的活交给 QSS 来干,而不是像 Flutter 一样什么都是 Widget。当然这只是通常的做法,其实写 Qt 也可以完全抛弃 QSS 直接硬写样式,结果就是像工控机上通常的那样。
再说说非工控机上的客户端。其实这块显然已经不可阻挡地要被 Web 统治了,无论最后胜出的是 Electron/Tauri 还是什么横空出世的某个框架。以前像是 Office 这种重量级应用还可以说 Web 性能太差,必须用 Qt。现在的问题是 WASM 出来了,而且 Web 的性能越来越好,越来越多复杂场景直接在 Web 实现,比如在线文档、Notion 甚至 VSCode。
在这里又要提一嘴 Flutter 了。Flutter 现在全端发力,也可以上桌面端了,还能上 Web。但这东西一直都是叫好不叫座,在 Web 端,用 Flutter 意味着要放弃整个前端社区,去用 Flutter 的小社区,意味着放弃各浏览器精心为 JS 优化了十几年的引擎,在性能上也没有优势;在桌面端上,Flutter Desktop 看起来没啥戏,为数不多的性能优势只是相比 Electron 有性能优势,和 Tauri 打得难解难分,目前体验下来一堆 API 调不了,社区生态又起不来,只有 Flutter 开发者会考虑用 Flutter 写 Desktop,而不是那些 Qt/Electron 使用者去用你的 Flutter Desktop——那可不就是寄了,Electron 是能吸引 Qt 开发者转 Electron 的,而 Qt 是能吸引 WPF 用户转到 Qt 的。
其实 Flutter 的思路还是挺有意思的,Widget 一层套一层虽然确实很傻逼,但看着还是挺清楚的,至少比 CSS 要清楚。但是 CSS 那边现在有了个 Tailwind CSS,大家直接把样式写在 class 里,不写 CSS 了,倒也很清楚,而且没有 Widget 一层套一层那么傻逼。但我个人觉得吧,Stateful Widget 写两个类很傻逼,Dart 自己也很傻呗——别的语言搞缝合是为了彰显自己语言本身的优势,怎么就有个 Dart 就是为了缝而缝呢,整个设计逻辑都不统一,感觉是一堆精神分裂的语言设计师合伙搞出来的,说白了就是没有特色,什么特性都要抄来,但又不知道自己为什么要抄,解决了什么问题,是真没啥意思。Dart 本身其实也就是 Google 那边的一个 KPI 项目,估计是没啥设计哲学的,本来就是打算暴死的,没想被 Flutter 整活了,实在是造化弄人啊。这和 Go 的情况还不一样,虽然 Go 的“大道至简”设计哲学很神必又很逆天,但它确实是有设计哲学的。
而 C++ Qt 其实已经不适合在客户端领域和 Web 方案竞争了。即使要竞争,也不如 PyQt/PySide 来得方便。由于本身只是库函数的移植,PyQt/PySide 的性能是与 C++ Qt 理论上一致的,而且更易上手,并且能够轻松对接 Python 生态。C++ Qt 为数不多的优势只是性能——而正如上面所说,单纯的性能优势并不重要。Tauri、Flutter Desktop 都可以达到可接受的性能优势。而需要死扣性能的应用,又不太可能选择 Qt 这种跨平台的方案,肯定是优先原生。
因此我说 Qt 在衰落,而且 Qt 工程师本身又没太多技术含量——并且这行也没几个岗位需要你有技术含量,而“Qt 工程师没技术”这一事实又导致情况进一步恶化,更加没有公司打算用 Qt 开发复杂应用——尽管理论上 Qt 完全能够胜任复杂应用,而且 Qt 工程师也可以学得很深入和专业,但在人才这块,拿什么去和 Web 前端比呢?
Qt 这些年做出了一点努力,如 QML 和 QtQuick,但这终究只是适用于 Qt 自己的生态,而这种努力我们看到大多失败了。Qt 自身设计优秀,性能良好,但一方面 C++ 本身学习门槛高,另一方面受到 Web 冲击太大。Qt 本身极其强大,包罗万象,提供了一个巨大的工具链,根本不是 Electron 这类只能被称作“方案”的技术能比的。但问题是,有几个人在乎呢?我为什么一定要用 C++ 开发 GUI 呢?这就是 Qt 的问题。