桌面軟件開發框架大賞

語言: CN / TW / HK

本文基於海康威視桌面端技術專家劉曉倫在「 RTC Dev Meetup • 杭州站丨大前端時代的業務架構和跨端實踐 」活動中分享內容二次整理。

以下正文:

今天要與大家分享 19 款桌面軟件開發框架,我將它們分了四類,然後分別就每個類別做相應的介紹,希望通過今天的分享,幫助大家在開發的過程當中少走一些彎路。

01 傳統桌面軟件開發框架

首先我們來聊一聊傳統的桌面軟件開發框架。這個類別中包含大家常見的 Qt、wxWidgets、GTK、FLTK、Swing 和 JavaFX。這六個框架有一些共同點:它們的歷史都很悠久,使用的開發者也很多,並且相應的社區也很成熟,其中包含了豐富的資料。此外,它們的功能都很強大,有大量成熟的案例,框架也很穩定。

但是它們用到的都是 相對來説都是比較成熟的技術,所以跟新興技術之間還是有所差距,所以使用起來比較困難。

1、Qt

Qt 的優點大家都可以在官網上看到,這裏不再贅述,其中有一點是 Qt 對各操作系統都做了很完善的封裝,比如網絡、文件剪切板等,如果要用系統級的 API,Qt 可以提供的非常豐富的 API。

對於 Qt 的問題這裏介紹一下我的感受,我認為 Qt 目前的問題是 發展方向不太專一,無法提供某些較大的模塊 ,在開發過程中可能會逐漸發現使用的模塊不太合適,進而廢棄這個模塊,包括很多 API 也是這樣,我之前用過的 Qt script 現在就已經被標記為廢棄了。

另外, Qt 的商業授權是不太友好的 。如果要開發一個商業應用,可能這裏要注意一下,有很多國內的公司都是收到過 Qt 的律師函要求收費的。Qt 還提供了很多組件,其中有一些複雜的組件對於控制 UI 的細節是比較難的,這裏就不再舉例了。

Qt 還有很多的動態鏈接庫,如果要做靜態鏈接也是比較難的,當然社區中提供了一種辦法,就是可以編譯 Qt 的源碼做靜態鏈接,但是這就又要涉及版權的問題了。

2、GTK

GTK 框架比較偏 Linux,在 Linux 中有很多桌面應用都是用 GTK 開發的,在 Windows 下 GTK 相對較少,並且在 Windows 系統下的靜態鏈接也是比較難的,甚至搭環境都比在 Linux 系統下要難得多。

另外,GTK 在 Windows 下也做了系統 API 的封裝,但是在 Windows 下的封裝比在 Linux 系統下的封裝要少一些。也就是説,有些 API 在 Linux 下能用,而在 Windows 下是不能用的,這樣的 API 不在少數。最後 GTK 的商業授權是非常友好的。

3、FLTK

FLTK 框架是 C++ 之父推薦使用的,它就是一個非常輕量的 GUI 框架,但是 輕量意味着功能是不足的,它的功能比較少,幾乎不做系統 API 的封裝 ,大部分都要開發人員自己用 C++ 編寫。這樣導致開發人員在每個平台上都要重新編寫,比如要開放一個跨平台的圖片應用,那麼在 Windows 下調用一些系統級的 API 進行實現,在 Mac 下可能又要實現一遍。

FLTK 的優點是它的產物很小,因此 它編譯出來的東西可以做到很小,而且性能也非常好 (比前兩個都好)。FLTK 的商業授權也很友好,可以支持靜態鏈接。但是 FLTK 有一些不足,就是因為它是一個 GUI 框架,因此在繪製 GUI 組件這方面是不太好的。

我在使用 FLTK 的時候發現,在其中做動畫控制、組件疊加(這時用到就是絕對定位,就需要對組件的層級進行控制)都會遇到問題。另外,在繪製圓角的時候,雖然 FLTK 提供了相關的功能,但是用户還要控制圓角的特殊大小、某一個圓角出現等,這些都要寫非常複雜的代碼。

4、wxWidgets

wxWidgets 跟前面 3 個框架有所區別,它是基於操作系統的 API 來做桌面應用的,也就是説,在 Windows 下開發一個桌面應用時,看起來就像是傳統的 Windows 桌面軟件的風格,在 Mac 下則是 Mac 的風格,而前面三個都有自己的自繪引擎。

也就是説,在前面三個框架中做一個按鈕,不管用什麼樣的繪製方式,在三個平台下表現都是一致的,但是 wxWidgets 在三個平台上都是按照三個平台自己的 API 來繪製這個按鈕的。wxWidgets 提供了非常多的操作系統的 API,並且可以做到靜態鏈接,但小問題比較多。

5、Swing/JavaFX

Swing /JavaFX 是基於 Java 的技術棧來做桌面應用的,因為要依賴 JVM,所以系統 API 比較多,但性能會一般,這兩個框架可能相對來説用得少一些。

如果大家在這幾個桌面軟件框架當中做選擇的話,我個人推薦還是用 Qt。

02 新興桌面軟件開發框架

剛才我們説的一些框架可能用的技術比較陳舊,大家開發起來比較麻煩。新興的框架,比如微軟的 MAUI、谷歌的 Flutter Desktop 和 JetBrains 公司的 Compose Multiplatform,都是採用非常新的技術來做的,開發起來很容易,開發體驗也非常好。

但是因為這幾個框架都比較新,基本上都是今年發佈的正式版(最早是 Compose Multiplatform 發佈的,然後依次是 lutter Desktop 和 MAUI),所以 社區相對來説不如前面幾個框架成熟,資料和成功案例也相對來説少一些

1、MAUI

MAUI 是用 XAML 是寫界面和邏輯的,大家如果用 WPF 寫過軟件的話,應該會對這項技術很熟悉。MAUI 用 C# 編寫業務邏輯,只兼容 Windows 操作系統和 Mac 操作系統。MAUI 在 Linux 下是社區提供的一套支持體系,可能會有一些問題。另外,MAUI 是依賴 .NET 框架的,API 比較多,並且支持移動端(這三個框架都是支持移動端的,新興的開發框架都兼容移動端的開發)。

2、Flutter Desktop

Flutter Desktop 是使用 dart 編寫界面邏輯的,它的組件比較豐富,並且支持 Win 10 操作系統(之前的操作系統就不太支持了),API 是比較少的,需要開發人員自己來寫。

3、Compose Multiplatform

Compose Multiplatform 依賴 JVM,是用 Kotlin 編寫邏輯的界面和邏輯的,有消息説將來可能會推出 Kotlin/native*,這樣就可以不用依賴 JVM 了,但是這可能還比較遙遠的事情。Compose Multiplatform 的組件也是比較豐富的,大家都知道 Java 社區中有很多框架、模塊等都可以使用,並且也是支持應用端的。

在這幾類框架裏中我推薦大家使用 Flutter Desktop,雖然它們都是新興的框架,所以很難説哪一個將來會更受歡迎, 但是根據它們的共同點(技術更現代化、更加易用、資料較少、社區不成熟、成功案例較少、用户較少、不穩定),我還是推薦 Flutter Desktop。

03 基於瀏覽器的桌面軟件開發框架

基於瀏覽器的桌面軟件開發框架相對較多,比如 Electron、NW.js、CEF、Sciter、WebView2、webview 和 TAURI。其中使用 Electron 比較多,也已經非常成熟。它們的共同點是它們可以複用瀏覽器的技術,比如 html、JS 和 CSS 等一系列生態中的組件。

除此之外,它們還可以做非常絢麗的界面,因為 Web 技術發展這麼年,CSS、html 等在標記和控制界面特性方面的技術都已經非常成熟,不像剛才提到的 FLTK 要做疊加動畫效果都非常困難, 如果用這些技術做這些界面會非常從容。但這些框架的功能也是有強有弱。

1、Electron/NW.js

Electron 和 NW.js 這兩個框架是非常相似的技術,它們都是把 Chromium 與 Node.js 集成到一起,讓開發者可以只使用前端技術開發桌面應用。如果要訪問系統的 API,就用 Node.js 提供的 API,當然也有一些特殊的 API,比方創建桌面圖標、訪問剪切板、控制窗口大小等,是 Electron 框架本身提供的,而不是 Node.js 提供的,也不是傳統 HTML 系統提供的,是在其中做了一些附加的操作,當然 NW.js 也有。

這兩個框架的作者都有很深的淵源,這裏就不細説了。我個人覺得 NW.js 實現起來相對來説比較巧妙,對開發者比較友好,而 Electron 維護更給力,社區也很龐大。

2、CEF/WebView2

CEF 和 WebView2 框架都是直接基於 Chromium 開發的。CEF 的歷史比較悠久,而且更靈活,大家可以通過這個框架進行自由的控制,API 也更多。

WebView2 是微軟的短期團隊提供的一個框架,這個框架也是直接基於基於 Chromium 做的封裝,它提供了 .NET 和 C++ 的 API,大家可以用 .NET、C++ 或者 C#語言去操作這個框架,目前還不支持 MAC(將來可能會支持)。

相對來説 CEF 更像作者個人在維護,WebView2 就更像一個團隊,但是因為 WebView2 不開源,所以也沒法參與。

3、webview/TAURI

webview 和 TAURI 使用操作系統內配置的瀏覽器核心,比如應該在 Windows 下部署,那麼就用 WebView2;如果在 Mac 下部署,就用 WKWebView;如果在 Linux 下部署,就用 webkitgtk 來做渲染,因此這裏可能就會有一些兼容性的問題。

在做前端的時候經常會碰到一些兼容性的問題,但是目前來看,因為它們都是比較現代的瀏覽器核心了,所以這個問題還沒有這麼明顯。另外,TAURI 是使⽤ Rust 開發的,如果要選擇這個框架,可能還得熟悉 Rust 語言。

4、Sciter

Sciter 是一個比較特殊的框架,這裏把它單列出來,Sciter 做了很多的削減,可以把產物的體積縮減到 10M 以內,前面幾種框架基本上只要把瀏覽器核心分發給用户,即使壓縮過後也得 60M。

Sciter 以前有一個自己的腳本叫 TIscript,現在用的是 QuickJS,它的功能非常強大,而且集成了 skia 的核心版本。我不知道大家有沒有關注過一個叫作 rustdesk 的項目,之前它選擇的就是 Sciter 框架,當然這個框架的小問題也會比較多。

如果大家選擇這類框架,我推薦使用 Electron/CEF 框架。如果團隊中沒有 C++ 開發人員,或者不易於使用 C++ 進行開發應用,就選擇 Electron;如果有 C++ 開發人員,而且應用非常注重性能,就選擇 CEF。

04 即時渲染桌面軟件開發框架

即時渲染相對應用的是保持模式的桌面應用框架,一般做桌面應用都是哪裏需要更新,就更新哪裏,框架會進行渲染。但是即時渲染是不一樣的,它是每刷新一幀,就會把顯示的內容都更新一遍,也就是説每一幀都會全部更新一遍。

所以 這類框架有一個共同的特點,就是它們要消耗 CPU 和 GPU 資源 ,傳統框架的配置都是保持模式,如果不更新是不會做渲染的。另外,這種框架與遊戲應用可以無縫對接,但是傳統應用案例比較少,小問題比較多,且尚在發展中。

1、Dear ImGui

即時渲染桌面軟件開發框架中,Dear ImGui 比較流行,最近作者在開發 Dock 模式,估計今年有可能會推出,到時候大家可以去嘗試一下。

它的開發方式是比較特別的,就是每個循環都在做渲染。比如使用 Dear ImGui 做事件開發時,會將某一個變量設置為 true 或者 false, 在這一輪渲染的過程當中是 true,在它下一輪渲染過程當中,我發現變成 false 了,我們就認為觸發了某個事件。而不是像 web 開發領域中,當出現一個 event 時,另一個組件就可以接收到它。

2、Nuklear

Nuklear 是使⽤ C 語⾔開發的,更貼近 C 開發者的習慣,⽤户相對 Dear ImGui 更少、⼩問題更多。

3、RmIui

RmlUi 比較特殊,它不是即時渲染框架,但是卻有即時渲染框架的通病,就是用它開發應用之後會持續消耗 CPU 和 GPU 資源,它可以使用 HTML 和 CSS 描述界面,上手相對比較難,開發非常靈活,界面也很靈活,資源消耗相對更多。

我最近一直在用這個框架,也跟作者進行了深入的交流。這個框架開發出來的應用程序可以做到 2M 左右,它可以解析你的 HTML,做一些非常特殊的效果,比如陰影、漸變之類的動畫,但是它很小,不像瀏覽器一樣,即使壓縮也得 60 多兆,這也是它的優勢。

這幾類框架中我個人推薦 RmlUi,如果到作者的項目中進行提問,他基本上隔天就會回覆。

05 總結

在做總結之前,我先簡述一下這幾個框架的對比。

其實我們在介紹傳統的桌面開發框架的時候,Qt 和 wxWidgets 內置的組件也有基於瀏覽器的, 就是 QWebEngin 和 wxWebView,QWebEngin 封裝的是 Chromium 的核心,其實與 CEF 和 QWebEngin 挺像的,但是很多人在用 Qt 的時候,是把 CEF 集成到 Qt 中,反而不用 QWebEngin。

他們堅持的觀點就是 QWebEngin 還不成熟,性能力相對來較弱,不如 CEF,但是目前來看,我個人認為,在 Qt 6.2 和 Qt 6.3 之後,QWebEngin 的 API 會更多,應用的需求更容易滿足。

wxWebView 更像是 webview 和 TAURI,它也是在不同的操作系統上使用操作系統的瀏覽器核心,這裏就不多説了。

再看一下 RmlUi 和 Sciter 的對比。RmlUi 可以用 html 和 CSS,Sciter 也可以用 html 和 CSS,因為 Sciter 集成了 QuickJS,所以它也可以寫 JS 代碼(但是也得寫 C++,因為你不可能不用操作系統的 API,但是它的 C++可能會比 RmlUi 的 C++ 代碼量要少很多)。兩個框架都不支持全部的 html 和 CSS 規範。

如果要選一個桌面軟件開發框架,應該確認側重哪方面的能力,我認為有三方面的能力是需要注重的:

  • 界面的描述能力 :比如佈局、元素定位、圓角、陰影、漸變
  • 事件處理能力 :比如鼠標事件、鍵盤事件、觸屏事件、媒體播放結束、網絡狀態變更等
  • 異步處理能力 :處理業務邏輯的時候,界面渲染工作不能暫停

另外,桌面軟件開發框架各有各的優勢,比如軟件開發邏輯很複雜,而且要快速地完成,那麼 BrowserCore 可能是一個不錯的方式,因為用前端技術來編寫速度更快,但是如果軟件需要更少的資源消耗和更快的運行速度,那麼就需要考慮 Native 方式。

最後,要做桌面應用開發需要了解一些底層知識,比如多線程、多進程的控制;各種通信協議;⽇志收集;版本控制;設計模式與架構原則;本地數據控制;操作系統。

06 問答環節

1、用 Electron 怎麼處理 crash?

Electron 也有非常多問題,它也會崩潰,並且有崩潰報告的收集方式,收集這些報告之後還要進行分析,但是分析出來的崩潰報告實並不能很明確地反映到底是哪一行代碼、哪一段業務出了問題。很多時候崩潰報告中可能更多的是説明一個指針指向的內存出現了問題,這時一種方法是儘量聯繫用户復現問題;第二種方式是做大量的自動化測試,收窄問題的範圍,將其侷限在一定的範圍內再做精細化處理;第三種方式就是做 AB 測試。

2、Electron 開發的應用安裝包太大這個問題有沒有好的解決辦法。另外,開發者該如何開發 Electron 應用的守護進程。

這是兩個問題。第一個問題就是包太大的問題,這個其實是挺難解決的,在立項之前就應該跟團隊負責人溝通好需求,是要快速的業務開發,還是更高的性能,更小的體積?如果要更小的體積,那麼就放棄業務開發效率。可以使用 C++ 做一些工作,只是會消耗更長的時間和更多的資源。在打包的時候,要先確認是否用的是 LZMA 壓縮格式,這種格式可以壓縮得更小一點,但是小不了多少,最低可能還是 60 多兆。

至於怎麼做守護進程,這個問題現在有兩種辦法,一種是寫一個獨立的應用,在 Electron 啟動的時候應用就可以隨之啟動,然後它守護 Electron 進程。如果 Electron 進程崩潰的時候,就由它來啟動 Electron 進程。

另一種方法是分析應用為什麼崩潰,是主進程崩潰了,還是渲染的時候崩潰了,你如果主進程崩潰了,儘量還是要找到其崩潰的原因,因為一旦主進程崩潰,那麼所有渲染都會失敗;如果是渲染進程崩潰了,那麼可以在主進程中打開一個其他的進程,來保證將渲染崩潰的通知發送給用户,由用户重啟渲染進程,或者自動重啟。