Qt小知識4.QWindow和QWidget

1 引言

QWindow 和 QWidget 都是 Qt 框架中用於創建和管理窗口的類,但它們在設計上服務於不同的目的和場景。這兩者的區別不僅體現在 API 設計上,還體現在它們在 Qt 框架中的角色和使用方式上。

2 典型區別

2.1 繼承結構和依賴

  • QWidget 繼承自 QObject 和 QPaintDevice,是所有窗口部件的基類。它是 Qt Widgets 模塊的一部分,主要用於傳統的桌面應用程序,依賴於 Qt 的 QApplication。
  • QWindow 直接繼承自 QObject 和 QSurface,代表一個可以有可視化輸出的窗口。它是 Qt GUI 模塊的一部分,可以用於更接近系統底層的窗口創建,依賴於 Qt 的 QGuiApplication。

2.2 使用場景

  • QWidget 適合於需要豐富交互界面的傳統桌面應用程序開發,提供了按鈕、文本輸入框等內置界面元素,以及佈局管理器來自動管理元素佈局。
  • QWindow 更多用於需要直接使用 OpenGL 或 Vulkan 這類底層圖形API進行渲染的場景,或者是當需要創建一個不附加任何傳統控件的輕量級窗口時。

2.3 繪圖和渲染

  • QWidget 支持 Qt 的繪圖機制,可以通過重寫 paintEvent 方法並使用 QPainter API 實現繪圖。
  • QWindow 的繪圖通常依賴於更底層的圖形系統,例如直接與 OpenGL 上下文集成。雖然 QWindow 也可以使用 QPainter 通過 QBackingStore 進行繪圖,但這不是其主要用途。

3 爲什麼引入QWindow?

  • 更清晰的分層架構
    在 Qt 5 之前的版本中,所有的窗口部件都是基於 QWidget 構建的,這意味着即使是不需要複雜部件和佈局系統的簡單窗口,也需要引入整個 QWidget 系統。QWindow 的引入提供了一個更輕量級的選擇,允許創建窗口而不必帶上全部 QWidget 的開銷。

  • 支持現代圖形APIs
    QWindow 提供了一個平臺無關的窗口句柄(handle),這使得開發者可以更直接地使用 OpenGL、Vulkan、DirectX 等現代圖形API來進行底層渲染。這對於需要高性能渲染的應用程序,如遊戲或高端圖形模擬,是非常重要的。

  • 促進 Qt Quick 的發展
    隨着 Qt Quick 和 QML 的引入,需要一個能夠與新的場景圖(scene graph)渲染系統無縫集成的窗口類。QWindow 扮演着這個角色,它可以容納一個完整的 Qt Quick UI,與底層圖形系統有效協作。

  • 跨平臺的窗口管理
    QWindow 封裝了操作系統的窗口管理功能,提供了跨平臺的窗口創建、事件處理、窗口狀態管理等,這使得開發者可以寫出更加跨平臺通用的代碼,而不需要關心底層操作系統的特定實現。

  • 變得更加模塊化
    隨着開發者對模塊化應用程序的需求日益增加,QWindow 類使得 Qt 框架能夠提供更加模塊化的組件。開發者可以選擇只使用圖形模塊來創建窗口和管理底層圖形,而不必加載和依賴更多的 QWidget 功能。

3 依賴關係

在 Qt 5 之前,Qt 的 Widgets 系統和其窗口系統是緊密耦合的,QWidget 直接處理所有與窗口相關的操作,如顯示、事件處理等。隨着 Qt 5 的推出以及 Qt Quick(基於 QML 的高性能界面技術)的引入,Qt 架構師重新設計了圖形和窗口系統的底層架構來提高其性能和靈活性。QWindow 被引入爲這個新架構的核心組件之一。

從 Qt 5 開始,QWidget 的實現在內部是依賴於 QWindow 的。這是 Qt 爲了整合其圖形和窗口系統架構做出的設計決策。這種依賴關係主要體現在:每個 QWidget(或者更具體地說,每個 QWidget 的頂層窗口)背後都有一個 QWindow 實例負責實際的窗口管理和底層圖形操作。

3.1 如何理解?

  • 窗口實例:當你創建一個 QWidget 並且使其成爲一個窗口(即沒有父對象或者通過調用 setWindowFlags 方法),Qt 內部會爲這個 QWidget 創建一個 QWindow 實例。這個 QWindow 實例是實際上與操作系統層進行交互的對象,負責窗口的顯示、事件的接收等。對於嵌入在其他 QWidget 中的 QWidget,它們共享同一個 QWindow 實例,因爲在操作系統層面,它們實際上屬於同一個窗口。

  • 繪圖與渲染:雖然 QWidget 和 QWindow 都可以進行繪圖和渲染操作,但它們的目的和方法不同。QWidget 的繪圖是基於 QPainter 的,更適合傳統的 GUI 應用程序。而 QWindow 則給予了開發者直接使用 OpenGL 或 Vulkan 等現代圖形 API 的能力。在 QWidget 中,繪圖最終還是通過它關聯的 QWindow 實現的,因爲所有的圖形輸出都是通過操作系統的窗口系統完成的。

3.2 實際應用

在實際的應用程序設計中,開發者通常不需要直接處理 QWindow,除非他們在進行一些較爲底層的圖形操作或創建高度定製化的窗口。QWidget 和 QWindow 的設計讓 Qt 能夠支持從簡單的桌面應用程序到複雜的圖形密集型應用程序的廣泛需求。

雖然從API使用者角度看 QWidget 和 QWindow 是分開的,但從 Qt 的內部實現來看,QWidget 的窗口展示功能是依賴 QWindow 的,這樣做既保留了 Qt Widgets 的高層次抽象方便開發傳統應用,又能從底層支持現代的圖形顯示需求。

4 總結

使用 QWidget 創建圖形用戶界面相對簡單,並且可以直接利用 Qt 的豐富的控件和佈局系統。而選擇 QWindow 可能需要更多底層的操作,但它可以更靈活地與底層圖形API集成,適用於特定的高性能渲染場景或當需要直接控制渲染循環時。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章