Qt 布局管理器
在一個顏值當道的今天,無論買衣服,買車還是追星,顏值的高低已經變成了大家最看重的(不管男性女性都一樣,千萬別和我說你不是);而對於程序猿來說,開發一款軟件,不再只註重邏輯和穩定性,美觀和用戶友好性也是我們不得不關註的一個重點了。
我們進入正題,今天主要和大家分享一下Qt方面關於布局管理器的使用;
一、基本概念
Qt 提供了幾種在窗口部件上管理子窗口部件的基本方式。一共有3 種方法用於管理窗體上子窗口部件的布局:絕對位置法、人工布局法和布局管理器法。相比於使用固定尺寸和位置,布局提供了功能強大且極具靈活性的另一種方案。使用布局後,編程人員無需計算尺寸和位置,布局可以自動進行調整,符合用戶屏幕、語言以及字體的要求。
1.絕對位置法
這種方法是最原始的拖放窗口部件的方法。它對窗體的各個子窗口部件分配固定的大小和位置,是通過調用基類QWidget 提供的setGeometry()函數來實現的。
所以絕對位置法有很多缺點:
1> 用戶無法改變窗口的大小,當父窗口改變時,子窗口不能做出相應的調整。
2>如果用戶選擇的字體太大或者翻譯成多國語言,特別是俄語,很多都會顯示不全被截斷。
3> 對於不同風格的平臺,這些窗口部件可能會具有並不合適的尺寸大小。
4>必須人工計算這些位置和大小。這樣做不僅非常枯燥而且極易出錯,並且還會讓後
期的維護工作變得痛苦萬分。
很顯然,使用這種方式管理GUI 應用程序大大降低了程序員的開發效率,降低了應用
程序的質量和適應性。
2.人工布局法
這種方法的核心是通過重載QWidget::resizeEvent(QResizeEvent*)函數來使得子窗口
的的大小尺寸總是和父窗口的大小成比例,也就在一定程度上減輕了計算量,但是在其中也
要通過setGeometry()函數來設置子窗口部件的位置和大小。在程序的規模比較小,並且不需要時常變更設計的情況下,絕對位置法勉強可以勝任。但是它就像前面的絕對位置法一樣,仍然需要計算許多手寫代碼中的常量,尤其是當設計被改變的時候,這種情況更加突出,而且它並沒有消除文本會被截斷的危險。輔以社會自子窗口部件的大小提示,應該可以規避這種風險,但是這樣會使代碼變得尤為復雜。
3.布局管理器法
這種方式是使用Qt 設計用戶界面、組織管理Qt 窗口部件的最好方法。布局管理器為
窗口部件提供了能變化的默認值(sensible default sizes),可以隨著窗口部件大小的變化,對子窗口部件的大小和位置做出適當的調整。
二、詳細使用說明
QLayout 類是Qt 的幾何管理器的基類,它派生自QObject 類和QLayoutItem 類,是一
個抽象基類,必須被派生類所重新實現。它的派生類主要有QBoxLayout, QGridLayout, QFormLayout 以及QStackedLayout。而QBoxLayout
又有兩個主要的Qt4 子類,QHBoxLayout 和QVBoxLayout
1、水平布局管理器:QHBoxLayout,按水平方向組織管理控件;
2、垂直布局管理器:QVBoxLayout,按垂直方向組織管理控件;
3、網格布局管理器:QGridLayout,按照二維網格組織管理控件;
4、表單布局管理器:QFormLayout,表單布局管理器主要用作管理界面上的輸入窗口部件( input widgets)以及和它們相連的標簽窗口部件(labels)。
5、棧布局管理器:QStackeLayout,類似於棧的方式管理控件,不過Qt設計器不知什麽原因沒有提供它的布局管理器(我認為開發人員覺得前幾種已經能滿足幾乎所有的布局需要,棧布局使用太過復雜,不如用一個控件代替),提供了一個棧控件(QStackedWidget);在實際應用中使用前三種混合基本都能滿足設計需求。
我們來看,第一種水平布局:
效果如圖:1.1
[attachment=15390]
1.1
第二種垂直布局:
效果如下圖1.2
[attachment=15391]
1.2
第三種 網格布局:
效果如下圖 1.3
[attachment=15392]
1.3
第四種 表單布局
效果如下圖 1.4
[attachment=15393]
1.4
第五種是棧布局,我的4.7.0 版本,Qt Designer 的窗口部件盒沒有可視化的提供對棧布局管理器的支持,只提供了一個棧部件QStackedWidget,作用與棧布局管理器類似。因此,在使用Qt Designer 繪制GUI界面時,完全可以使用QStackedWidget 來代替QStackedLayout。在此不做贅述。
2.1下面來講講案例:
當然是用設計器拖出來最簡單方便,我們後面再用代碼寫;
1.用設計器 添加五個控件;
2.選中是個button點擊右鍵選擇布局,我們選擇柵格布局(你可以看情況自己選擇合適的);
[attachment=15395]
2.1
3.將剛才布局的控件和文本框一起選中,點擊右鍵再選擇你需要的布局方式(我們選擇水平);
[attachment=15395]
2.2
4.效果圖如下:
2.3
這裏我們就要註意調整空白和控件之間間距的問題;
2.4
1.空白(margin)和間距(spacing)
每種布局都有兩個重要的屬性,空白和間距。空白指的是整個布局四周距離窗體邊緣
的距離;間距指的是布局管理器內部各個窗口部件之間的距離。空白屬性即margin(),間距屬性即spacing(),它們的默認值是有窗體的風格決定的。Qt 的默認風格下,子窗體部件的margin()的值是9 英寸。spacing()的值與margin()相同。如果要設置這兩個值可以通過setMargin()和setSpacing()。註意,從Qt4.3 開始,margin()屬性已經逐漸不再被Qt4 所推薦,更好的設置空白的方法是使用setContentsMargins()方法,
它的原型如下:
void QLayout::setContentsMargins ( int left, int top, int right, int bottom )
其中,left, top, right, 和bottom 表示環繞在布局周圍的空白。對於QGridLayout 和QFormLayout,不要使用setSpacing()方法,而是要分別使用setHorizontalSpacing()和setVerticalSpacing()方法來設置水平和垂直方向
2.大小約束(size constraint)
影響布局方式的另一種方法是設置它的子窗口部件的最大大小、最小大小或固定大小。這些是通過設置sizeConstraint 屬性來完成的。該屬性值是一個枚舉常量,定義了布局的大小約束的模式。表列出了它所有可能的取值,它的默認值是QLayout::SetDefaultConstraint。獲取和設置該屬性值可以通過QWidget::layout()來獲取主窗口部件的布局管理器,然後可以調用QLayout::sizeConstraint()函數來查看當前的設置情況,然後再通過QLayout::setSizeConstraint()函數來設置該布局管理器的sizeConstraint 屬性。這兩種函數的原型如下:SizeConstraint sizeConstraint () const
void setSizeConstraint ( SizeConstraint )其中,SizeConstraint 的取值可以在QLayout類的枚舉中得到;
QLayout::SetDefaultConstraint 0 主窗口部件的最小尺寸設置為minimumSize(),除非該窗口部件已經有一個最小尺寸
QLayout::SetFixedSize 3 主窗口部件的尺寸設置為sizeHint(),並且不允許改變該窗口部件的尺寸
QLayout::SetMinimumSize 2 主窗口部件的最小尺寸設置為minimumSize(),並且該窗口部件不能夠變得更小
QLayout::SetMaximumSize 4 主窗口部件的最大尺寸設置為maximumSize(),並且該窗口部件不能夠變得更大
QLayout::SetMinAndMaxSize 5 主窗口部件的最小尺寸設置為minimumSize(),最大尺寸設置為
3.大小策略(size policy)
一個窗口部件的大小策略會告訴布局系統應該如何對它進行拉伸或收縮。Qt 為它所有
的內置窗口部件都提供了合理的默認大小策略值,但是由於不可能為每一種可能產生的布局
都提供唯一的默認值,所以在一個窗體中,開發人員改變它上面的一個或兩個窗口部件的大
小策略是非常普遍的現象。一個QSizePolicy 既包含一個水平分量也包含一個垂直分量。
可以通過QSizePolicy 找到對應的枚舉值;
4.伸縮因子(stretch factor)
除了大小策略中包含的水平方向和垂直方向兩個分量之外, QSizePolicy 類還保存了水平方向和垂直方向的一個伸縮因子。這些伸縮因子可以用來說明在增大窗體時,對不同的子窗口部件應使用的不同放大比例。即需要設置QSizePolicy::horizontalStretch 和
QSizePolicy::verticalStretch 的值來實現。默認情況下,被布局管理器組合在一起的窗
口部件的伸縮因子是相等的,都為0。
2.2 移除布局
選擇想要移除的布局,點擊右鍵或者如下圖在設計器工具欄上有個“打破布局”
如圖:
[attachment=15398]
2.5
2.3 一些快捷鍵
常見的布局操作所對應的快捷鍵。
水平布局Ctrl+1 將選中的界面元素置於一個水平布局中;
垂直布局Ctrl+2 將選中的界面元素置於一個垂直布局中;
柵格布局Ctrl+5 將選中的界面元素置於一個柵格布局中;
表單布局Ctrl+6 將選中的界面元素置於一個表單布局中;
分裂器水平布局Ctrl+3 創建一個分裂器水平布局,並將選中的界面元素置於其中;
分裂器垂直布局Ctrl+4 創建一個分裂器垂直布局,並將選中的界面元素置於其中;
調整大小Ctrl+J 調整布局的大小,以使得位於其中的元素能夠恰當的顯示自身內容。關於這方面的內容,可以參見QWidget::adjustSize()函數;
破除布局Ctrl+0 破除選中的布局;
2.4 手寫代碼
QWidget *pWidget = new QWidget;
pWidget->setWindowTitle("Calculator");
pWidget->show();
QLineEdit *pText = new QLineEdit(pWidget);
pText->setMinimumSize(150,100);
QPushButton *pBtnAdd = new QPushButton("+",pWidget);
QPushButton *pBtnSub = new QPushButton("-",pWidget);
QPushButton *pBtnMul= new QPushButton("*",pWidget);
QPushButton *pBtnDiv= new QPushButton("/",pWidget);
QVBoxLayout *pVBox = new QVBoxLayout(pWidget);
QGridLayout *pGBox = new QGridLayout();
pVBox->addWidget(pBtnAdd);
pVBox->addWidget(pBtnSub);
pVBox->addWidget(pBtnMul);
pVBox->addWidget(pBtnDiv);
pVBox->setSpacing(10);
pWidget->setLayout(pVBox);
pGBox->addWidget(pBtnAdd,0,0);
pGBox->addWidget(pBtnSub,0,1);
pGBox->addWidget(pBtnMul,1,0);
pGBox->addWidget(pBtnDiv,1,1);
pVBox->addWidget(pText);
pVBox->addLayout(pGBox);
pVBox->setMargin(12);
pWidget->setLayout(pVBox);
效果如下圖2.6:
2.6
2.5 總結
當界面元素較為復雜時,應該毫不猶豫的盡量使用網格布局,而不是使用水平和垂直布局的組合或者嵌套的形式,因為在多數情況下,後者往往會使“局勢”更加復雜而難以控制。網格布局賦予了界面設計器更大的自由度來排列組合界面元素,而僅僅帶來了微小的復雜度開銷。當要設計的界面是一種類似於兩列和若幹行組成的形式時,使用表單布局要比網格布局更為方便些。
上面分享了自己關於布局的基礎使用方式的理解,若有不對之處敬請指正
Qt 布局管理器