桌面軟體開發框架大賞

liulun 發表於 2022-05-26
框架

本篇文章全部源自作者的親身經歷,不是官網隨便搬來的。

Qt

幾乎是C++領域最流行的跨平臺桌面端軟體開發框架了,

這個框架是兩個挪威人在1995年建立的,發展至今可以說歷史相當悠久,穩定性也很有保障。

很多大公司都在用它做介面比如金山的WPS。

它內建了自繪引擎,也就是說介面上的一個按鈕,一個文字框,都是Qt的引擎自己畫的,這保證了基於Qt開發的軟體介面在不同作業系統上看起來是一模一樣的。

它提供了大量的與介面無關但與軟體開發息息相關的API,比如、網路、檔案系統、剪下板等,而且讓這些API在不同的作業系統下都有效,這極大的節省了開發人員的時間。

但它也有一些缺點,比如在處理一些特殊需求上很不方便,比如:目前Qt有沒有比較好解決高分屏下縮放顯示的方案?Qt沒有真正完美的無邊框解決方案嗎?等,

在一些元件的渲染上也會出一些隱藏的較深的問題(QListItem),一旦遇到,就很難解決。

Qt近年來不太專一,qml,qtquick等,搞了很多,而且這些新玩意兒一直不溫不火,有些模組做了又廢棄了,比如:qt script,搞來搞去,搞的模組繁多且複雜,用起來不是很舒服。

Qt有介面描述語言(XML描述介面),可以通過設計器拖拽空間設計介面,編譯期介面描述語言被轉義成C++程式碼,效能上沒啥損失。

Qt商業授權不太友好,開發商業應用一定要謹慎,之前聽說有公司為此付出了高額的版權費。個人開發者可以免費使用。

Qt的免費版本不允許靜態連結,會有版權上的限制,但開發者還是可以通過一些特殊的編譯方法靜態連線Qt的庫的。

除了使用C++開發Qt應用外,開發者還可以使用其他語言開發Qt應用,

最流行的就是使用Python基於PyQt做Qt應用了,其他語言的繫結不是很成熟,但PyQt仍然有版權的問題。

GTK

GTK是1997年建立的,也非常成熟穩定,

是C語言開發的,但有很多語言的繫結,比如官方支援的JavaScript、Rust等,當然用C++語言操作GTK也很方便,

它也有自繪引擎(Cairo),也提供了大量系統相關的API,

商業授權也非常友好,基於GTK開發商業軟體不用擔心收到律師函的問題,

雖然它是一個跨平臺桌面軟體,但它似乎只在Linux作業系統領域流行,有非常多的Linux桌面軟體都是基於GTK開發的。

這也直接導致GTK的維護者很重視Linux領域的發展,而忽視Windows和Mac領域。

這個框架提供的很多API,只在Linux下有,Windows和Mac下沒有。這樣的API數量眾多。

甚至在Windows下編譯一下GTK的原始碼都要比Linux下難很多。

而且GTK的渲染引擎在Windows下效能表現也不如在Linux下好。

GTK在Windows上也沒辦法靜態連線,倒不是因為版權的問題,而是它依賴了MSYS2的一些庫,這個庫用於在Windows上模擬Linux環境,這也是為什麼GTK在Windows上表現不佳的原因之一。

另外,由於GTK是C語言開發的,所以開發風格也很C語言化,這對於部分開發者來說可能覺得繁瑣。

wxWidgets

wxWidgets是1992年英國的一個大學教授開創的跨平臺GUI軟體,也非常成熟穩定,商業授權非常友好。

它沒有自繪引擎,而是對不同平臺下的介面API做了整合和封裝,

這樣開發者在Windows下開發的軟體看起來就是Windows視窗風格、Linux開發的軟體看起來就是Linux視窗風格,

這對於某些軟體來說,正是他們想要的,但要想搞一些花哨的特效就沒那麼容易了。它同樣也提供了大量的系統相關的API供開發者使用。

它是C++開發的,所以對C++開發者非常友好,

除此之外它還支援靜態連線,也就是說開發個應用不用分發給使用者一大堆dll。

它會有些小問題,比如我之前提的:wxEVT_NOTIFICATION_MESSAGE_DISMISSED event emit twice,但總體來說還是非常穩的。

除了開發的介面比較死板外,沒啥大的問題。

FLTK

FLTK是1998年建立的跨平臺開源GUI框架,歷史悠久,商業授權友好,而且C++之父也用它,

它非常輕量級,支援靜態連線,一個簡單的應用編譯後只有500K左右,非常贊,

它有自己的自繪引擎,用的是OpenGL,

但它的重繪機制是按區域重繪的,如果元件A所在的區域上存在元件B,那麼A元件重繪時,會把B元件的給重繪掉,開發者必須自己寫程式碼處理這種情況。

想象一下,如果你想實現一個A元件fade out的同時B元件fade in的效果,就會非常麻煩。

FLTK提供的一些元件樣式都比較刻板,繪圖API也比較少,

你想實現一個漂亮一點的圓角按鈕(它內建圓角按鈕的圓角大小是不能改的),必須自己畫,而且還得藉助一些非常奇葩的手段才行(如果你想知道,可以聯絡我)

它是C++開發的,但API不夠現代,用起來總體還算舒服的,

它有Rust繫結:fltk-rs。它提供了一些與介面無關的作業系統API,但非常少,幾乎可以忽略。

Duilib

是2010年國內一個開發者開發的GUI開發框架,

因為底層基於DirectUI開發,所以只支援Windows平臺,不支援跨平臺,

開源協議友好,商用沒有任何問題(需要附加Lincence檔案),

國內有很多大廠基於這個技術做桌面端應用,比如網易、騰訊、百度,

這個框架是基於C++開發的,對C++開發者友好。

但框架本身還有一些問題,比如對高分屏支援不佳、特殊控制元件繪製上也有一些小問題,

除了介面相關的API外,幾乎沒有提供系統級的API,作者純粹是用愛發電來開發這個框架,所以更新不是很及時。

相對來說網易基於Duilib開發的分支更完善一些:NIM_Duilib_Framework,新增了高分屏支援、多國語言、整合了多執行緒處理的支援,

但環境搭建相對比較麻煩。如果開發者要用這個框架,一定要用develop分支下的程式碼,master分支下的程式碼問題很多,這個框架看上去也是作者一個人努力的成果。

Sciter

Sciter是2006年建立的跨平臺閉源GUI框架,足夠穩定,

它商業授權不友好,但個人開發者可以隨便用(只能用動態連結庫),一旦公司規模超過3人,就得買版權了(也就有權靜態連線了)。

它內部封了一個瀏覽器核心,但對這個瀏覽器核心做了大量的精簡,不像Electron和NW.js動輒上百兆的體積,它只要6M左右就夠了。底層的繪製引擎我記得是谷歌的skia,

開發者可以使用HTML,CSS,JS來建立介面,當然由於底層是一個閹割版的瀏覽器核心,這也意味著有些瀏覽器特性它是不支援的,

比如CSS3的flex佈局,它就不支援(但它提供了自己的flex佈局實現方式)。

以前它使用自研的一個指令碼語言(和JavaScript很像),自從整合了Fabrice Bellard大神的QuickJs之後,就全面支援JavaScript了。

另外,它還對一些特殊的場景做了內建的支援,比如渲染大列表。

它使用C++開發,對C++開發者很友好,有Rust、go、Python等語言的繫結,但都是社群提供的,質量堪憂。

有很多知名廠商都用這個庫做介面,比如360、teamviewer、賽門鐵克等。

另一個庫RmlUi和Sciter很像,可以看成Sciter的替代框架,

但RmlUi這個專案有三屆作者,一個一個的棄坑不知道新任作者會不會棄坑,目前還不是很成熟,比如我正在嘗試幫作者解決的CJK輸入法的問題,目前還不推薦大家使用這個框架。

CEF

CEF是2008年創立的,基於Chromium的跨平臺GUI框架,穩定且商業授權友好,

國內很多大廠都用的CEF:比如微信桌面端、網易雲音樂桌面端(Win)、QQ桌面端、微信桌面端、MATLAB、FoxMail、OBS Studio,裝機量破億(過於保守)。

由於它幾乎封了一個完整的Chromium,所以體積非常大,但它支援所有的HTML\CSS\JS特性,

它幾乎不提供任何與作業系統相關的API,建立個托盤圖示、讀寫個檔案啥的,都要開發者自己完成,

它是C/C++開發完成的,對C++使用者非常友好,它有go\python\java等語言的繫結,但都是社群提供的,質量值得擔憂。

它對Chromium封裝的很好,避免了開發者直接與Blink、V8、Chromium等複雜的程式碼打交道,

很多功能都有預設實現方式,遵從約定由於配置原則,有經驗的C++開發者可以很輕鬆的駕馭CEF框架。

由於Chromium是版本弟,所以CEF版本釋出也非常頻繁,很多被標記為穩定的版本,還是會出一些莫名其妙的問題,選一個好的版本非常重要。

與Electron一樣,它也是分主程式和渲染程式的,所以開發者要非常嫻熟的運用跨程式通訊的技術,

雖然CEF提供了跨程式相關的API,但複雜度還是有點高的,使用的時候要認真細心。

這是我在掘金寫的關於CEF的系列課程:https://juejin.cn/book/7075387142121193502

MAUI

這是微軟的跨平臺GUI框架,不僅僅支援桌面端,還支援移動端,但官方並不支援Linux的桌面端(黑人問號,感覺與微軟近些年向開放、開源的大方針相悖),

這個框架新的狠,至今還沒釋出穩定版。

它是.NET平臺下的GUI框架,有自繪引擎,對C#開發者很友好,介面依然是用XAML描述的,可能很多人一聽到XAML就直接棄坑了。

XAML表現力確實弱一些,我覺得WPF沒火起來跟XAML有直接關係。

這是我個人的觀點,也是相對來說吧(比HTML/CSS弱)。很多人覺得XAML挺好,也很有道理的。我無意與大家爭論,也不想改我的原文,關於這方面的問題,請大家不要評論了。

使用這個框架開發桌面應用得封一個.NET框架給使用者,當然有了.NET框架應用程式訪問一般的系統級API也就不成問題了。

Compose Multiplatform

這是JetBrains搞的跨平臺GUI框架,也非常新,前段時間剛剛推出1.0.0版本,

但這個版本還不是很穩,至少比Flutter Desktop的第一個穩定版要差很多。幾乎沒什麼人用。

它的自繪引擎用的是Google的skia,這個自繪引擎穩的很,Chrome和Flutter都是用的它,

所以繪製、渲染之類的工作不太會出問題。比Java生態圈裡的Swing和JavaFx要好很多。

JetBrains的東西當然對Kotlin開發者友好啦,Java生態下的很多東西你都能用,訪問系統級API也沒啥大問題,同樣也得考慮封一個JRE給使用者。

flutter-desktop

這是谷歌的跨平臺開發框架,開源、免費、文件齊全、投入力度大且持久,

桌面端同樣也新的很,Windows版本剛剛發穩定版,Mac版本還沒穩定。

如果你完全沒搞過移動端的flutter,想用這個框架開發桌面應用,那麼意味著你要學的東西還挺多的。好在dart和flutter入門都不是很難,學習曲線比較平緩。

由於flutter在移動端積累了很多年,所以介面上的一些東西在desktop端都比較穩(skia自繪引擎),

與作業系統相關的東西還不成熟,生態也不太好,

比如你想訂製一下視窗的標題欄,想訪問一下注冊表這類工作可能得自己想辦法。

不過它有類似FFI的支援,跟C/C++語言打交道很方便。

開發者直接使用Dart語言描述介面,這會導致眾多大括號巢狀在一起的問題,可能很多開發者不習慣。

使用flutter-desktop開發的應用程式打包後體積還比較大

webview2

這是微軟Edge瀏覽器團隊推出的跨平臺GUI引擎,是閉源的,

目前只支援Windows,對C#和C++開發者友好,

如果使用C#開發,就得考慮把.NET執行時分發給使用者,

如果使用C++開發,就得自己處理系統級API的操作,webview2本身是不對系統級API做封裝的。

這個框架推出有一小段時間了,但很多API也還不穩定,

更值得擔憂的是這個團隊,他們前不久剛剛放棄了自己的瀏覽器核心轉而使用Chromium瀏覽器核心,不知道他們會不會放棄webview2這個框架。

它的優勢是可以複用系統當中已存在的webview2二進位制資源,

也就是說它雖然封了一個Chromium瀏覽器核心,但如果你可以確定客戶電腦已經存在了基於webview2開發的應用,你的安裝包體積可以足夠小。

它也是多程式架構,甚至比Electron還要多一個程式(為了複用二進位制資源),資源佔用比較多。

更詳細的介紹可以看我這篇文章:https://zhuanlan.zhihu.com/p/428560381

webview

這個庫使用作業系統的瀏覽器引擎來達到減小安裝包體積的問題,

Mac上使用Cocoa/WebKit,Linux上使用gtk-webkit2,Windows 10上使用Edge(也就是上一個小節裡提到的webview2),

它是不支援Win7的。由於不同的OS會用不同的瀏覽器核心,所以開發者使用它開發跨平臺應用時要考慮前端程式碼瀏覽器相容的問題。

開源且免費(MIT)有go、Rust、Python等語言的繫結,不過官方支援的是go語言,C和C++,

操作瀏覽器的API非常少,不支援自定義scheme,更別提系統級API了。

TAURI

採用的技術方案與webview類似,所以安裝包也足夠小,非常新,還沒釋出穩定版,開源免費。webview框架碰到的問題TAURI都有,

使用Rust開發,將來會支援Deno,作者說將來會直接使用webview的技術來支援多平臺,

NW.js

NW.js最早把Chromium和Node繫結到一起,用前端知識做介面,用Node技術訪問作業系統,

最早叫node-webkit,在2012年建立。

NW.js基於MIT開源,可以無憂使用。

微信小程式開發工具好像是用NW.js開發的(幾年前調研過)。作者是英特爾的員工,英特爾的一些工具也是用NW.js開發的。

除了Chromium和Node的能力外,NW.js自己也封裝了一些系統級API,類似托盤圖示、剪下板、系統選單這種,但數量明顯比Electron要少。

NW.js可以在多個視窗間共享同一個Node.js上下文,而且還可以通過配置讓Node的上下文和Dom上下文混合,這給開發者帶來了很多便利。心智負擔減少很多。

不像Electron要時刻想著程式間通訊,哪些模組當前程式不能用這類問題。

NW.js雖然起步早,但奈何沒有殺手級應用,周邊的生態和工具鏈沒發展起來。

用的人越來越少,維護的投入也不如Electron大,再加上Chromium更新非常頻繁,導致NW.js的有些API也不是很穩,惡性迴圈加劇。

Electron

https://www.electronjs.org/

Electron的作者曾經在NW.js團隊工作過(NW.js專案貢獻第二多的人就是Electron的作者),

後來輾轉到了github公司,於2013年在建立了Electron,

也是個開源免費的產品。由於VSCode、slak等國際型產品都選擇了Electron,所以從者甚眾,

生態和周邊工具鏈也完善的多。雖然開發方式上有點蹩腳的地方(多程式架構及模組歸屬程式),但瑕不掩瑜。

Electron每建立一個視窗都會多一個程式,這使Electron建立視窗的效率不高(秒級),

NW.js有複用程式的機制,即使新視窗載入完全不同域的頁面也不會建立新的程式(毫秒級)。

這也是為什麼很多基於Electron開發的應用都使用Dom模擬彈窗的原因。

無論是瀏覽器相關的API,還是系統級API,Electron提供的都比NW.js多。

ImGui

https://github.com/ocornut/imgui

這個GUI框架的實現原理和開發方式可謂獨樹一幟

它在一個無限迴圈裡不斷的重繪整個介面,

別的GUI框架都是哪裡更新了重繪哪裡,它是無論有沒有更新,一股腦全部重繪,而且一直在重繪,

這樣做對於一些不支援GPU的客戶端來說CPU消耗會略高一些,不過總起來說還算好

它對遊戲開發者很友好,很多遊戲都整合它來做使用者互動(遊戲內的一些設定介面、聊天介面之類的)

它支援很多種繪製引擎比如OpenGL,Directx,Vulkan等

打包後體積很小,也就幾百K的樣子

也有一些小問題,比如:要用很蛋疼的方法在介面內使用同一種字型的不同的字號

你如果打算使用這個庫,我建議你不要選master分支,而選docking分支(這個分支下有很多amazing的特性)

與這個框架類似的還有:https://github.com/Immediate-Mode-UI/Nuklear

總結

我們介紹了這麼多框架,可以說各有各的特點,有的成熟穩定,有的執行高效,還有一些框架單憑業務表達能力取勝,開發者在做技術選型時往往會難以抉擇。

這裡我總結了三個判斷桌面軟體開發框架是否優秀的底層邏輯,這可以幫助我們開發者認清真相,做出最優選擇。

第一,是否具備獨立的介面描述語言( UI DSL )。

這非常重要,是一個框架表達業務的重要能力。

類似 WPF 的 XAML、qt ui 檔案裡的 XML、 HTML + CSS 都屬於介面描述語言,這都屬於一種通過特化的 XML 來描述介面的方式;

還有一種通過程式碼來描述介面的方式,flutter、qml 和 Compose Multiplatform 都以類似這樣的介面描述語言來描述介面的。

如下虛擬碼是 Compose Multiplatform 的介面描述形式:

panel {
  row {
    checkBox(...)
    row {
      textField(...) 
    }
  }
}

但無論如何,顯而易見的是,沒有任何一個介面描述語言能比得上 HTML + CSS 組合。

想想看:HTML 裡各種五花八門的語義化標籤和 Dom 操作技巧、CSS 裡的佈局方式、偽元素、動畫描述等,就會明白這一點。

第二,是否擁有強大的事件處理機制。

作為一個 GUI 應用,與使用者的互動、與裝置的互動必不可少,

這就涉及到形形色色的事件,比如,與裝置有關的滑鼠事件、鍵盤事件、觸屏事件、網路狀態變更事件等,

與介面元素狀態有關的介面載入完成事件、媒體播放結束事件、元素大小改變事件等。

另外,能接收這些事件還遠遠不夠,還得處理事件冒泡、事件捕獲、事件分發,等等。

我認為 JavaScirpt 與瀏覽器核心的結合來處理各種各樣的事件也是表現出眾。

而且經歷了數十年的發展,這套組合的事件系統也相當成熟穩定。

第三,是否擁有強大的非同步、並行處理機制。

開發者不能在處理使用者業務邏輯的時候,讓介面渲染工作阻塞,

這就需要一個強大的非同步、並行處理機制,

如果讓開發者自己去建立執行緒並完成這些工作,無疑是又麻煩又會增加開發者的心智負擔。

JavaScirpt 雖然是單執行緒執行的語言,但瀏覽器核心是多執行緒的(還是多程式的),

所以 JavaScript 與瀏覽器核心結合後,開發者既不用為開發多執行緒應用而苦惱,又不用為沒有多執行緒的支援而手足無措。

 

從以上三方面的技術需求來看,在桌面 GUI 應用裡封裝一個瀏覽器核心還是非常有價值的,

這樣開發者就可以用 HTML + CSS 強大的能力來描述介面,

用 JavaScript 強大的事件處理機制和非同步處理機制來完成使用者互動。

 

web相關的技術之所以勝出,並不是這些技術的設計者有多厲害,而是這20多年間,有大量的人湧入了這個領域,前赴後繼的推動著它前進。

其他任何一個領域都沒有這麼熱火朝天的景象。推薦大家看看我的另一個回答:

用Web相關的技術做GUI應用的優勢是,讓開發者可以把大部分精力投注在業務本身上,而不是處理與GUI相關的技術細節。

實際上所有的框架,都應該是這個目的,比如ORM框架,目的應該是讓開發者把大部分精力投注在業務與資料之間的關係上,而不是管理關係型資料的技術細節。

當然這肯定是有損耗的,在效能、穩定性、資源消耗上,都會有所削減。

而且,因為有框架的存在,開發者很難深入到框架內部做一些特殊的事情。

比如,我們該如何修改HTML的排版渲染機制呢?

所以,有些框架注重效能,有些框架注重開發效率,開發者做選擇題的時候也應該衡量這兩個問題,你的應用對哪些方面要求多一些呢?

你如果要開發一個視訊監控系統,沒多少業務功能,但要24小時不間斷的記錄視訊資料,隨時調取某一段時間的視訊資料,這種應用可能Qt是最好的選擇。

你如果要開發一個類似飛書的團隊協作應用,業務邏輯複雜的一塌糊塗,

而且要在短時間內滿足更多使用者的需求,佔領更多的市場,

那麼Electron可能是更好的選擇(目前飛書已經不再用Electron了,他們自己編譯了Chromium核心,自己封了一個類似CEF的框架)

 

目前微軟、谷歌、JetBrains等公司都非常重視桌面端開發框架,也在推各自的框架產品,說明桌面應用領域並沒有沒落,反而應該更加受到重視。

雖然移動端應用大行其道,但我認為,只有生活、社交、輕娛樂等方向上的應用在移動端有較好的發展。

文件協作、大型遊戲、開發工具、專業管控軟體等應用還是在PC端發展的更好一些,畢竟PC端有更多樣的輸入輸出裝置、更廣闊的顯示和互動的空間,更強的儲存和計算能力。

希望桌面軟體開發領域的從業者都能獲得幸福。

滿屏荒唐言,一把辛酸淚,一把辛酸淚,一把辛酸淚...