Qt學習筆記(五)——物件模型、佈局管理器
一、物件模型
Qt 使用 moc,為標準 C++ 增加了一些特性:
- 訊號槽機制,用於解決物件之間的通訊,可以認為是 Qt 最明顯的特性之一;
- 可查詢,並且可設計的物件屬性;
- 強大的事件機制以及事件過濾器;
- 基於上下文的字串翻譯機制(國際化),也就是 tr() 函式;
- 複雜的定時器實現,用於在事件驅動的 GUI 中嵌入能夠精確控制的任務整合;
- 層次化的可查詢的物件樹,提供一種自然的方式管理物件關係。
- 智慧指標(QPointer),在物件析構之後自動設為 0,防止野指標;
- 能夠跨越庫邊界的動態轉換機制。
moc 其實實現的是一個叫做元物件系統(meta-object system)的機制。正如上面所說,這是一個標準 C++ 的擴充套件,使得標準 C++ 更適合於進行 GUI 程式設計。雖然利用模板可以達到類似的效果,但是 Qt 沒有選擇使用模板。按照 Qt 官方的說法,模板雖然是內建語言特性,但是其語法實在是複雜,並且由於 GUI 是動態的,利用靜態的模板機制有時候很難處理。而自己使用 moc 生成程式碼更為靈活,雖然效率有些降低(一個訊號槽的呼叫大約相當於四個模板函式呼叫),不過在現代計算機上,這點效能損耗實在是可以忽略。
QObject
是以物件樹的形式組織起來的。當你建立一個QObject
物件時,會看到QObject
的建構函式接收一個QObject
指標作為引數,這個引數就是 parent,也就是父物件指標。這相當於,在建立QObject
物件時,可以提供一個其父物件,我們建立的這個QObject
物件會自動新增到其父物件的children()
列表。當父物件析構的時候,這個列表中的所有物件也會被析構。(注意,這裡的父物件並不是繼承意義上的父類!)這種機制在 GUI 程式設計中相當有用。例如,一個按鈕有一個QShortcut
(快捷鍵)物件作為其子物件。當我們刪除按鈕的時候,這個快捷鍵理應被刪除。
QWidget
是能夠在螢幕上顯示的一切元件的父類。QWidget
QObject
,因此也繼承了這種物件樹關係。一個孩子自動地成為父元件的一個子元件。因此,它會顯示在父元件的座標系統中,被父元件的邊界剪裁。
Qt 引入物件樹的概念,在一定程度上解決了記憶體問題。
當一個QObject
物件在堆上建立的時候,Qt 會同時為其建立一個物件樹。不過,物件樹中物件的順序是沒有定義的。這意味著,銷燬這些物件的順序也是未定義的。Qt 保證的是,任何物件樹中的 QObject
物件 delete 的時候,如果這個物件有 parent,則自動將其從 parent 的children()
列表中刪除;如果有孩子,則自動 delete 每一個孩子。Qt 保證沒有QObject
在 Qt 中,儘量在構造的時候就指定 parent 物件,並且大膽在堆上建立。
二、佈局管理器
所謂 GUI 介面,歸根結底,就是一堆元件的疊加。我們建立一個視窗,把按鈕放上面,把圖示放上面,這樣就成了一個介面。在放置時,元件的位置尤其重要。我們必須要指定元件放在哪裡,以便視窗能夠按照我們需要的方式進行渲染。這就涉及到元件定位的機制。Qt 提供了兩種元件定位機制:絕對定位和佈局定位。
絕對定位就是一種最原始的定位方法:給出這個元件的座標和長寬值。但如果使用者改變了視窗大小,比如點選最大化按鈕或者使用滑鼠拖動視窗邊緣,採用絕對定位的元件是不會有任何響應的。針對這種變化的需求,Qt 提供了另外的一種機制——佈局——來解決這個問題。你只要把元件放入某一種佈局,佈局由專門的佈局管理器進行管理。當需要調整大小或者位置的時候,Qt 使用對應的佈局管理器進行調整。
Qt 提供了幾種佈局管理器供我們選擇:
QHBoxLayout
:按照水平方向從左到右佈局;QVBoxLayout
:按照豎直方向從上到下佈局;QGridLayout
:在一個網格中進行佈局,類似於 HTML 的 table;QFormLayout
:按照表格佈局,每一行前面是一段文字,文字後面跟隨一個元件(通常是輸入框),類似 HTML 的 form;QStackedLayout
:層疊的佈局,允許我們將幾個元件按照 Z 軸方向堆疊,可以形成嚮導那種一頁一頁的效果。