漫談QWidget及其派生類 二

2021-07-24 18:43:50 字數 3518 閱讀 3979

本文接下來試圖看看 qlayout 與視窗的幾何尺寸控制。

注意:本文只是試**釋,qlayout其實沒有任何神秘的東西,它所有的功能離開它你也都可以做。但這並不是鼓勵大家不使用qlayout。

始終記住一點:要改變乙個widget的大小,只有move()、resize()、setgeometry()這3個東西可用,當然,對於帶裝飾器的頂級視窗,你還可以通過滑鼠等改變大小或移動視窗位置(但這個不在本文討論範圍內)。

乙個qwidget 或其派生類

對於乙個視窗(window)來說,還要區分:

看起來還蠻複雜的哈,列個表看看。

framegeometry()

幾何尺寸(位置+大小)

對於視窗,包含視窗裝飾器

x()y()

pos()

只包含位置資訊(左上角座標)

move()

只移動位置

geometry()

幾何尺寸(位置+大小)

不包含視窗裝飾器

width()

height()

rect()

size()

只包含大小資訊

setgeometry()

改變 位置+大小

resize()

只改變大小

關鍵記住一點:要程式內改變乙個widget的大小,只有move、resize、setgeometry這3個東西可用。不要被qlayout干擾,它一點都不神秘,它也只能老老實實去呼叫這類函式。

用個例子看看吧,如果

int main(int argc, char *argv)

}widget.show();

return a.exec();

}只需要挨個設定一下幾何尺寸,似乎也不複雜嘛。是吧?

其實這也不是大問題,我們只需要在子類化qwidget,覆蓋(override)它的resizeevent()函式

void widget::resizeevent(qresizeevent *)

在這兒重新設定它上面的按鈕的位置和大小就行了。

這是個大問題,單一的widget還好解決,比如乙個按鈕,你可以根據文字、按鈕樣式等等計算乙個大小。可是對於復合的widget:比如我們例子中的widget中有64個按鈕,如果再將這樣的64個widget放於另外乙個widget中,會怎麼樣?

沒有什麼好辦法,仍然是需要我們乙個乙個進行計算。其實不是太難,但是操作特別繁雜。

只能是按鈕通知其parent(通過layoutrequest事件),而後parent重新排布子控制項,以獲得最佳顯示效果。

接下來,我們看看 qlayout 是如何解決這三個問題的。

layout 做哪些事情呢?

初始放置

將子widget乙個乙個放置到父widget上

layout 計算各個子widget大小,並呼叫setgeometry() 來設定

響應父widget變化

父widget大小變化時,子widget相應變化

layout 通過監聽父widget的qresizeevent事件來實現

響應子widget變化

子widget的最佳大小變化時

(比如給按鈕設定新的text)

讓父物件的layout 重新計算幾何尺寸

當乙個widget的大小變化後,會生成qresizeevent事件(這時widget所關聯layout就開始重新計算嘍...)。

我們知道,事件都是通過qwidget::event()派發的:

bool qwidget::event(qevent *event)

}bool consumed = receiver->event(e);

...而後layout開始工作

void qlayout::widgetevent(qevent *e)

else

break;

...

恩,注意看上面**:如果reciever是widget而且有layout,該事件先送到layout的widgetevent()中。然後才會通過event()派發到達大家熟悉的resizeevent()等函式。

前面的resize比較容易理解,如果子widget的大小想變化,如何通知layout呢?

通過void qwidget::updategeometry ()函式。

void qwidgetprivate::updategeometry_helper(bool forceupdate)

看看這段**,如果parent有layout布局,直接讓布局無效(強制layout重新計算大小)。

而如果parent沒有布局呢?恩,思想也比較簡單:它給父widget傳送 layoutrequest 事件。注意:如果我們不使用布局的話,面對這種情況,我們就要自己處理這個事件嘍。

這個其實似乎是最有趣的,qlayout如果知道它負責控制的各個widget該有多大的大小呢?

qwidget::sizepolicy()

這3個東西為layout提供一些大小資訊

對於自定義widget,子類化時你可能需要提供這些資訊

qwidget::sizehint()

qwidget::minimumsizehint()

熟悉這3個東西,以及各個qlayout派生類的使用,不然,你可能會抱怨——qlayout太難用了

比如:前面的例子,我們64個按鈕,如果32個使用qgridlayout進行管理,32個不用layout進行管理。結果會怎麼樣?

其實不會怎麼樣。qgridlayout 負責對它管理的widget呼叫setgeometry,而你負責對自己管理的呼叫setgeometry。想怎麼放就怎麼放。(但是你要注意:最好別讓它們重合,不然...)

qmainwindow 上面放置很多的widget:

選單欄qmenubar

這些全是qwidget的派生類

工具欄q*******

狀態列qstatusbar

停靠視窗

qdockwidget

中心窗體

...

其實沒有什麼神秘的,一堆widget放置到了qmainwindow中,而且還會自動隨著qmainwindow變化。你很容易想到它預設就已經設定了乙個qlayout!

class qmainwindowlayout : public qlayout

{ q_object

...

這是乙個私有類,你不必關心細節,但是可以考慮:平時如何使用qlayout的?是不是要將你的widget加入到layout中??

在qmainwindow中,qmenubar、q*******等等都已經加入到了它的layout中,而且layout中為你留了乙個位置,就是中心窗體。

在qmainwindow,qmainwindowlayout管理的這些子widget布滿了幾乎整個窗體。所以:有人抱怨

漫談QWidget及其派生類 二

本文接下來試圖看看 qlayout 與視窗的幾何尺寸控制。注意 本文只是試 釋,qlayout其實沒有任何神秘的東西,它所有的功能離開它你也都可以做。但這並不是鼓勵大家不使用qlayout。始終記住一點 要改變乙個widget的大小,只有move resize setgeometry 這3個東西可用...

漫談QWidget及其派生類 二

本文接下來試圖看看 qlayout 與視窗的幾何尺寸控制。注意 本文只是試 釋,qlayout其實沒有任何神秘的東西,它所有的功能離開它你也都可以做。但這並不是鼓勵大家不使用qlayout。始終記住一點 要改變乙個widget的大小,只有move resize setgeometry 這3個東西可用...

漫談QWidget及其派生類 二

本文接下來試圖看看 qlayout 與視窗的幾何尺寸控制。注意 本文只是試 釋,qlayout其實沒有任何神秘的東西,它所有的功能離開它你也都可以做。但這並不是鼓勵大家不使用qlayout。始終記住一點 要改變乙個widget的大小,只有move resize setgeometry 這3個東西可用...