Qt小知識4.QWindow和QWidget
1 引言
QWindow 和 QWidget 都是 Qt 框架中用于創(chuàng)建和管理窗口的類,但它們在設(shè)計(jì)上服務(wù)于不同的目的和場景。這兩者的區(qū)別不僅體現(xiàn)在 API 設(shè)計(jì)上,還體現(xiàn)在它們在 Qt 框架中的角色和使用方式上。
2 典型區(qū)別
2.1 繼承結(jié)構(gòu)和依賴
- QWidget 繼承自 QObject 和 QPaintDevice,是所有窗口部件的基類。它是 Qt Widgets 模塊的一部分,主要用于傳統(tǒng)的桌面應(yīng)用程序,依賴于 Qt 的 QApplication。
- QWindow 直接繼承自 QObject 和 QSurface,代表一個(gè)可以有可視化輸出的窗口。它是 Qt GUI 模塊的一部分,可以用于更接近系統(tǒng)底層的窗口創(chuàng)建,依賴于 Qt 的 QGuiApplication。
2.2 使用場景
- QWidget 適合于需要豐富交互界面的傳統(tǒng)桌面應(yīng)用程序開發(fā),提供了按鈕、文本輸入框等內(nèi)置界面元素,以及布局管理器來自動(dòng)管理元素布局。
- QWindow 更多用于需要直接使用 OpenGL 或 Vulkan 這類底層圖形API進(jìn)行渲染的場景,或者是當(dāng)需要?jiǎng)?chuàng)建一個(gè)不附加任何傳統(tǒng)控件的輕量級窗口時(shí)。
2.3 繪圖和渲染
- QWidget 支持 Qt 的繪圖機(jī)制,可以通過重寫 paintEvent 方法并使用 QPainter API 實(shí)現(xiàn)繪圖。
- QWindow 的繪圖通常依賴于更底層的圖形系統(tǒng),例如直接與 OpenGL 上下文集成。雖然 QWindow 也可以使用 QPainter 通過 QBackingStore 進(jìn)行繪圖,但這不是其主要用途。
3 為什么引入QWindow?
-
更清晰的分層架構(gòu)
在 Qt 5 之前的版本中,所有的窗口部件都是基于 QWidget 構(gòu)建的,這意味著即使是不需要復(fù)雜部件和布局系統(tǒng)的簡單窗口,也需要引入整個(gè) QWidget 系統(tǒng)。QWindow 的引入提供了一個(gè)更輕量級的選擇,允許創(chuàng)建窗口而不必帶上全部 QWidget 的開銷。 -
支持現(xiàn)代圖形APIs
QWindow 提供了一個(gè)平臺無關(guān)的窗口句柄(handle),這使得開發(fā)者可以更直接地使用 OpenGL、Vulkan、DirectX 等現(xiàn)代圖形API來進(jìn)行底層渲染。這對于需要高性能渲染的應(yīng)用程序,如游戲或高端圖形模擬,是非常重要的。 -
促進(jìn) Qt Quick 的發(fā)展
隨著 Qt Quick 和 QML 的引入,需要一個(gè)能夠與新的場景圖(scene graph)渲染系統(tǒng)無縫集成的窗口類。QWindow 扮演著這個(gè)角色,它可以容納一個(gè)完整的 Qt Quick UI,與底層圖形系統(tǒng)有效協(xié)作。 -
跨平臺的窗口管理
QWindow 封裝了操作系統(tǒng)的窗口管理功能,提供了跨平臺的窗口創(chuàng)建、事件處理、窗口狀態(tài)管理等,這使得開發(fā)者可以寫出更加跨平臺通用的代碼,而不需要關(guān)心底層操作系統(tǒng)的特定實(shí)現(xiàn)。 -
變得更加模塊化
隨著開發(fā)者對模塊化應(yīng)用程序的需求日益增加,QWindow 類使得 Qt 框架能夠提供更加模塊化的組件。開發(fā)者可以選擇只使用圖形模塊來創(chuàng)建窗口和管理底層圖形,而不必加載和依賴更多的 QWidget 功能。
4 依賴關(guān)系
在 Qt 5 之前,Qt 的 Widgets 系統(tǒng)和其窗口系統(tǒng)是緊密耦合的,QWidget 直接處理所有與窗口相關(guān)的操作,如顯示、事件處理等。隨著 Qt 5 的推出以及 Qt Quick(基于 QML 的高性能界面技術(shù))的引入,Qt 架構(gòu)師重新設(shè)計(jì)了圖形和窗口系統(tǒng)的底層架構(gòu)來提高其性能和靈活性。QWindow 被引入為這個(gè)新架構(gòu)的核心組件之一。
從 Qt 5 開始,QWidget 的實(shí)現(xiàn)在內(nèi)部是依賴于 QWindow 的。這是 Qt 為了整合其圖形和窗口系統(tǒng)架構(gòu)做出的設(shè)計(jì)決策。這種依賴關(guān)系主要體現(xiàn)在:每個(gè) QWidget(或者更具體地說,每個(gè) QWidget 的頂層窗口)背后都有一個(gè) QWindow 實(shí)例負(fù)責(zé)實(shí)際的窗口管理和底層圖形操作。
4.1 如何理解?
-
窗口實(shí)例:當(dāng)你創(chuàng)建一個(gè) QWidget 并且使其成為一個(gè)窗口(即沒有父對象或者通過調(diào)用 setWindowFlags 方法),Qt 內(nèi)部會(huì)為這個(gè) QWidget 創(chuàng)建一個(gè) QWindow 實(shí)例。這個(gè) QWindow 實(shí)例是實(shí)際上與操作系統(tǒng)層進(jìn)行交互的對象,負(fù)責(zé)窗口的顯示、事件的接收等。對于嵌入在其他 QWidget 中的 QWidget,它們共享同一個(gè) QWindow 實(shí)例,因?yàn)樵诓僮飨到y(tǒng)層面,它們實(shí)際上屬于同一個(gè)窗口。
-
繪圖與渲染:雖然 QWidget 和 QWindow 都可以進(jìn)行繪圖和渲染操作,但它們的目的和方法不同。QWidget 的繪圖是基于 QPainter 的,更適合傳統(tǒng)的 GUI 應(yīng)用程序。而 QWindow 則給予了開發(fā)者直接使用 OpenGL 或 Vulkan 等現(xiàn)代圖形 API 的能力。在 QWidget 中,繪圖最終還是通過它關(guān)聯(lián)的 QWindow 實(shí)現(xiàn)的,因?yàn)樗械膱D形輸出都是通過操作系統(tǒng)的窗口系統(tǒng)完成的。
4.2 實(shí)際應(yīng)用
在實(shí)際的應(yīng)用程序設(shè)計(jì)中,開發(fā)者通常不需要直接處理 QWindow,除非他們在進(jìn)行一些較為底層的圖形操作或創(chuàng)建高度定制化的窗口。QWidget 和 QWindow 的設(shè)計(jì)讓 Qt 能夠支持從簡單的桌面應(yīng)用程序到復(fù)雜的圖形密集型應(yīng)用程序的廣泛需求。
雖然從API使用者角度看 QWidget 和 QWindow 是分開的,但從 Qt 的內(nèi)部實(shí)現(xiàn)來看,QWidget 的窗口展示功能是依賴 QWindow 的,這樣做既保留了 Qt Widgets 的高層次抽象方便開發(fā)傳統(tǒng)應(yīng)用,又能從底層支持現(xiàn)代的圖形顯示需求。
5 總結(jié)
使用 QWidget 創(chuàng)建圖形用戶界面相對簡單,并且可以直接利用 Qt 的豐富的控件和布局系統(tǒng)。而選擇 QWindow 可能需要更多底層的操作,但它可以更靈活地與底層圖形API集成,適用于特定的高性能渲染場景或當(dāng)需要直接控制渲染循環(huán)時(shí)。
每一步踏出,都是一次探索,一次成長。

浙公網(wǎng)安備 33010602011771號