## 11.3 基本布局實踐
基本布局主要包括:水平布局、垂直布局、柵格布局和表單布局這 4 種。在講解水平 布局和垂直布局之前,還要重點說一下它們的父類 -QBoxLayout,它也是使用比較多的,并 且包含了水平布局和垂直布局的一些共性特點。
### 11.3.1 QBoxLayout
使用 QBoxLayout 類可以創建一個布局,能夠把其中的窗口部件水平的或者垂直的按照直線排列。
之所以取名為“Box”,是由于 QBoxLayout 類把位于其內的空間均勻的劃分成若干個 “盒子”,并把各個窗口部件都放入一個盒子里面。
使用 QBoxLayout 創建的布局是有方向性的,主要是有水平和垂直兩個方向。當給定其 方向參數為 Qt::Horizontal 時,即表示水平方向,位于其中的窗口部件將水平排列成一 行,并且它們都會找到適合自己的大小。當給定方向參數為 Qt::Vertical 時,窗口部件將按 照垂直直線排列。布局內的其余空間是共享的,它們的尺寸可以由伸縮因子( stretch factors)來確定。
使用 QBoxLayout 類來創建一個布局是很容易的,做法是直接調用其構造函數,其原型 如下:
```
QBoxLayout::QBoxLayout ( Direction dir, QWidget * parent = 0 )
```
該構造函數它有兩個參數,一個是布局的方向,一個是父窗口指針,默認為 0 即當前窗口。布局的方向枚舉值如表 11-4 所示。
表 11-4 QBoxLayout 的方向枚舉值
| 常量 | 值 | 說明 |
| --- | --- | --- |
| QBoxLayout::LeftToRight | 0 | 從左到右水平排列 |
| QBoxLayout::RightToLeft | 1 | 從右到左水平排列 |
| QBoxLayout::TopToBottom | 2 | 從上到下垂直排列 |
| QBoxLayout::BottomToTop | 3 | 從下到上垂直排列 |
一個實例代碼如下:
```
//第 1 步
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton(tr("One"));
QPushButton *button2 = new QPushButton(tr("Two"));
QPushButton *button3 = new QPushButton(tr("Three"));
QPushButton *button4 = new QPushButton(tr("Four"));
QPushButton *button5 = new QPushButton(tr("Five"));
//第 2 步
QBoxLayout *layout = new QBoxLayout(QBoxLayout::LeftToRight,0);
//第 3 步
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);
//第 4 步
window->setLayout(layout);
//顯示窗口
window->show();
```
創建這種布局的一般步驟是:
第 1 步,創建要使用的窗口部件。
第 2 步,創建布局,并指定其方向和父窗口。
第 3 步,將窗口部件依次加入到布局中。
第 4 步,為應用程序程序窗口設置布局。
如上代碼所示,在其中通過注釋指出了各步驟對應的代碼行。這段代碼將創建 1 個名 為 window 的應用程序窗口,1 個名為 layout 的 QBoxLayout 實例,以及 5 個按鈕,布局方 向是從左到右的水平方向。圖 11-16 顯示了這個實例的效果,你會發現它與使用水平布局 的效果是一樣的。

圖 11-16 使用 QBoxLayout 類創建的布局效果
當然,在實際應用中,我們大多數情況下會直接使用 QBoxLayout 的兩個派生類,水平 布局和垂直布局,它們更加方便而且有針對性。
### 11.3.2 水平布局
水平布局把在其中的窗口部件按照一條直線水平排列。 QHBoxLayout 類用來創建水平 布局的實例。
一個簡單的手寫代碼創建水平布局的實例如下:
```
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton(tr("One"));
QPushButton *button2 = new QPushButton(tr("Two"));
QPushButton *button3 = new QPushButton(tr("Three"));
QPushButton *button4 = new QPushButton(tr("Four"));
QPushButton *button5 = new QPushButton(tr("Five"));
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);
window->setLayout(layout);
window->show();
```
使用手寫代碼創建水平布局大體需要下面這些步驟:
第 1 步,創建布局內的窗口部件。
第 2 步,創建一個水平布局的實例,也就是創建一個 QHBoxLayout 的實例,并將第 1 步創建的窗口部件加入到該布局之中。
第 3 步,調用 QWidget::setLayout()函數將該布局安裝到窗體上。設置了布局之后, 在該布局內的窗口部件將以 window 作為它們的父窗口。該實例的效果如圖 11-17 所示:

圖 11-17 水平布局效果
### 11.3.3 垂直布局
垂直布局把位于其中的窗口部件按照一條直線垂直排列。 QVBoxLayout 類用來創建一個 垂直布局的實例。
一個簡單的使用手寫代碼創建垂直布局的實例如下:
```
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);
window->setLayout(layout);
window->show();
```
使用手寫代碼創建垂直布局大體需要下面這些步驟:
第 1 步,創建布局內的窗口部件
第 2 步,創建一個垂直布局的實例,也就是創建一個 QVBoxLayout 類的實例,并將第 1 步創建的窗口部件加入到該布局之中
第 3 步,調用 QWidget::setLayout()函數將該布局安裝到窗體上。設置了布局之后, 在該布局內的窗口部件將以 window 作為它們的父窗口。該實例的效果如圖 11-18 所示:

圖 11-18 垂直布局實例效果
水平和垂直布局可以嵌套、組合使用,并且可至任意的深度。但在比較復雜的情況 下,使用柵格布局往往是更理想的做法。
### 11.3.4 柵格布局
柵格布局將位于其中的窗口部件放入一個網狀的柵格之中。柵格布局是這樣工作的:
它計算了位于其中的空間,然后將它們合理的劃分成若干個行( row)和列(column),并把每個由它管理的窗口部件放置在合適的單元之中,這里所指的單元( cell)即是指由行和列交叉所劃分出來的空間。
在使用柵格布局之前,需要在代碼中包含如下的頭文件聲明:
```
#include <QGridLayout>
```
創建柵格布局的大致步驟如下:
第 1 步,創建布局內的窗口部件。
第 2 步,創建柵格布局的實例,也就是創建一個 QGridLayout 類的實例,并將第 1 步 創建的窗口部件加入到布局之中。
第 3 步,調用 QWidget::setLayout()函數將布局安裝到窗體上。 一個典型的實例代碼如下:
```
nameLabel = new QLabel(tr("&Name:"));
nameLabel->setBuddy(nameLineEdit);
ageLabel = new QLabel(tr("&Age:"));
ageLabel->setBuddy(ageSpinBox);
QGridLayout *gridLayout = new QGridLayout;
gridLayout->addWidget(nameLabel, 0, 0);
gridLayout->addWidget(nameLineEdit, 0, 1);
gridLayout->addWidget(ageLabel, 1, 0);
gridLayout->addWidget(ageSpinBox, 1, 1);
setLayout(gridLayout);
```
我們來講解一下這段代碼。可以明顯的看出, QHBoxLayout 和 QVBoxLayout 的用法相當簡單明了,但是 QGridLayout 的用法則稍微有些麻煩。QGridLayout 的工作基于一個二維單 元格。在這個布局中,左上角的 QLabel 即 nameLabel 的位置是(0,0),而與之相應的 QLineEdit 即 nameLineEdit 的位置是(0,1)。以此類推,ageLabel 的位置是(1,0),而 ageSpinBox 的位置是(1,1)。它們都占用一列的值。
對于 QGridLayout::addWidget()的調用遵循如下的語法形式:
```
layout->addWidget(widget,row,column,rowSpan,columnSpan);
```
其中,widget 是要插入到布局中的子窗口部件,(row,column)是由該窗口部件所占用的左上角單元格,rowSpan 是該窗口部件要占用的行數,而 column 是該窗口部件要占用的列 數。如果省略了這些參數,則它們將會取默認值 1。
該示例的運行效果如圖 11-19 所示。

圖 11-19 柵格布局效果
在柵格布局中,行和列本質上是相同的,只是叫法不同而已。下面我們將重點討論 列,這些內容當然也適用于行。
在柵格布局中,每個列(以及行)都有一個最小寬度( minimum width)以及一個伸縮 因子(stretch factor)。最小寬度指的是位于該列中的窗口部件的最小的寬度,而伸縮因 子決定了該列內的窗口部件能夠獲得多少空間。它們的值可以通過 setColumnMinimumWidth()和 setColumnStretch()方法來設置。
此外,一般情況下我們都是把某個窗口部件放進柵格布局的一個單元中,但窗口部件 有時也可能會需要占用多個單元。這時就需要用到 addWidget()方法的一個重載版本,它的 原型如下:
```
void QGridLayout::addWidget ( QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan,Qt::Alignment alignment = 0 )
```
這時這個單元將從 fromRow 和 fromColumn 開始,擴展到 rowSpan 和 columnSpan 指定 的倍數的行和列。如果 rowSpan 或 columnSpan 的值為-1,則窗口部件將擴展到布局的底部 或者右邊邊緣處。
小貼士:柵格布局中的某個單元(cell)的長和寬,也可以說是柵格布局的行和列的尺寸 并不是一樣大小的。如果你想使它們相等,你必須通過調用 setColumnMinimumWidth()和 setColumnStretch()方法來使得它們的最小寬度以及伸縮因子都彼此相等。
如果 QGridLayout 不是窗體的頂層布局(就是說它不能管理所有的區域和子窗口部 件),那么當你創建它的同時,就必須為它指定一個父布局,也就是把它加入到父布局中 去,并且在此之前,不要對它做任何的操作。使用 addLayout()方法可以完成這一動作。
在創建柵格布局完成后,就可以使用 addWidget(),addItem(),以及 addLayout()方 法向其中加入窗口部件,以及其它的布局。
當界面元素較為復雜時,應該毫不猶豫的盡量使用柵格布局,而不是使用水平和垂直布局的組合或者嵌套的形式,因為在多數情況下,后者往往會使 “局勢”更加復雜而難以控 制。柵格布局賦予了界面設計器更大的自由度來排列組合界面元素,而僅僅帶來了微小的復雜度開銷。
當要設計的界面是一種類似于兩列和若干行組成的形式時,使用表單布局要比柵格布 局更為方便些。
### 11.3.5 表單布局
表單布局是從 Qt 4.4 開始被引入的。它把布局內的界面元素分成兩列,左邊的列通常 放置標簽(label)而右邊的列放置對應值的窗口部件,如 line edits,spin boxes 等等, 如圖 11-20 所示。表單布局在不同的平臺上與本地原生外觀相同,并且支持長的行形式,
如表 11-5 所示。

圖 11-20 使用表單布局
QFormLayout 這個類是從 Qt 4.4 以后引入的。在使用該類之前,需要包含如下的頭文 件聲明。
```
#include <QFormLayout>
```
在 QFormLayout 類出現以前,這種類似于兩列布局的情形我們通常使用 QGridLayout 來創建。而現在,使用 QFormLayout 則有更多的優勢:
**能夠適應不同的平臺,并且提供與本地原生平臺一致的觀感**
舉例來說,在 Mac OS X Aqua 和 KDE 平臺上通常要求標簽中的文本是右對齊的,而在 Windows 和 GNOME 平臺上則要求文本是左對齊的,QFormLayout 能夠很好的自動適應。
支持可折疊的長行(當其中的文本較多時) Support for wrapping long rows. 在便攜式設備上,文本太長以至于需要折疊的情況比較常見,但既要折疊而又要不影響顯示的效果則是比較困難的事情。現在的 QFormLayout 類可以很好的解決這個問題,它會判斷當前的情形是否需要折疊以及怎樣折疊才好。表 11-5 顯示了它的折疊策略。
表 11-5 QFormLayout 行折疊策略枚舉值
| 常量 | 值 | 說明 |
| --- | --- | --- |
| QFormLayout::DontWrapRows | 0 | 值域(即可輸入的文本行)總是在其對應的標簽(label)的旁邊,也就是不 折疊。這是默認的行折疊策略(采用了 Qt 擴展風格的情況除外)。 |
| QFormLayout::WrapLongRows | 1 | 標簽將獲得最大允許的自由空間,與它對應的值域則使用剩余的空間,如 果一行放不下,它將另起一行,也就是把自己折疊起來。這是采用 Qt 擴展 風格情況的默認行折疊策略。 |
| QFormLayout::WrapAllRows | 2 | 值域將總是在與它對應的標簽的下邊一行。 |
API
為創建標簽--(對應的)值域這種伙伴(buddy)類型的界面提供了豐富、方便的通過使用 addRow()函數(共有 6 種重載形式)或者 insertRow()函數(也有 6 種重載形式),我們可以簡便的創建一個 QLabel 窗口部件以及它的伙伴窗口部件。一個實例代碼 如下:
```
QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(tr("&Name:"), nameLineEdit);
formLayout->addRow(tr("&Age:"), ageSpinBox);
setLayout(formLayout);
```
如果同樣的情形使用 QGridLayout 來布局,則代碼如下:
```
nameLabel = new QLabel(tr("&Name:"));
nameLabel->setBuddy(nameLineEdit);
ageLabel = new QLabel(tr("&Age:"));
ageLabel->setBuddy(ageSpinBox);
QGridLayout *gridLayout = new QGridLayout;
gridLayout->addWidget(nameLabel, 0, 0);
gridLayout->addWidget(nameLineEdit, 0, 1);
gridLayout->addWidget(ageLabel, 1, 0);
gridLayout->addWidget(ageSpinBox, 1, 1);
setLayout(gridLayout);
```
對比這兩段代碼就可以發現,它們實現了相同的界面,而使用 QFormLayout 類則更簡單高效,并且不易出錯。表 11-6 顯示了該界面在不同的平臺下的默認觀感。
表 11-6 表單布局在不同平臺上的默認外觀

小貼士:標簽(QLabel)和它的伙伴(buddy)窗口部件
一個標簽窗口部件和一個窗口部件具有伙伴關系,即指當用戶按下激活標簽的快捷鍵 時,鼠標/鍵盤的焦點將會移到它的伙伴窗口部件上。只有 QLabel 的實例才可以有伙伴窗 口部件,也只有該 QLabel 實例具有快捷鍵(在顯示文本的某個字符前面添加一個前綴 &, 就可以定義快捷鍵)時,伙伴關系才有效。例如:
```
QLineEdit* nameLineEdit = new QLineEdit(this);
QLabel* nameLabel = new QLabel(tr("&Name"),this);
nameLabel->setBuddy(nameLineEdit);
```
該代碼定義了 nameLabel 標簽的快捷鍵為"Alt+P",并將行編輯框 nameLineEdit 設置為它的伙伴窗口部件。所以當用戶按下快捷鍵 "Alt+P"時,焦點將會跳至行編輯框 nameLineEdit 中。
在 Qt Designer 中,可以通過鼠標拖放操作快捷的建立 QLabel 和它的窗口部件的伙伴 關系,這需要切換到“伙伴編輯模式”。
由于 Qt 提供了許多的方法,所以使用表單布局時可以比較靈活的變換它的風格,經常 使用的方法有 setLabelAlignment()、setFormAlignment()、setFieldGrowthPolicy()、 setRowWrapPolicy()等。舉個例子,如果要在所有的平臺上都模擬出 Mac OS X 上的觀感, 但卻是用 Windows 上常見的標簽文本左對齊的規則,可以這樣寫代碼:
```
formLayout->setRowWrapPolicy(QFormLayout::DontWrapRows);
formLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
formLayout->setFormAlignment(Qt::AlignHCenter | Qt::AlignTop);
formLayout->setLabelAlignment(Qt::AlignLeft);
```
總結一下,創建表單布局的大致步驟如下:
第 1 步,創建布局內的窗口部件。
第 2 步,創建表單布局的實例,也就是創建一個 QFormLayout 類的實例,并將第 1 步 創建的窗口部件加入到布局之中。
第 3 步,調用 QWidget::setLayout()函數將布局安裝到窗體上。
讀者朋友可以通過前面的代碼驗證這些步驟。
### 11.3.6 刪除布局內窗口部件的方法
要從一個布局內刪除一個窗口部件,只需調用 QLayout::removeWidget()方法。其原型 如下:
```
void QLayout::removeWidget ( QWidget * widget )
```
這將刪除該布局內的 widget 窗口部件,但是并沒有把它從窗體界面上刪除。調用完該函數后,你需要為該窗口部件指定一個合適的幾何大小,或者干脆把它從界面上刪除。一個 實例代碼如下:
```
gridLayout->removeWidget(nameLabel);
nameLabel->setGeometry(9,9,50,25);
```
如果只是想使布局內的窗口部件隱藏起來,就可以調用 QWidget::hide()方法。然后調用 QWidget::show()方法可以使它再次顯示。使用方法比較簡單,讀者可以自行驗證。
如果往布局中添加一個窗口部件或者從布局中移除一個窗口部件,布局都會自動適應 所產生的這些新情況。如果對一個子窗口部件調用了 hide()或者 show(),也同樣能夠做到 自動適應。如果一個子窗口部件的大小提示發生了變化,布局將會自動進行調整,從而把新 的大小提示考慮進去。還有,布局管理器也會自動根據窗體中子窗口部件的最小大小提示和 大小提示,從總體上考慮,為這個窗體設置一個最小尺寸。
### 11.3.7 基本布局的綜合運用
本實例利用基本布局管理(QHBoxLayout、QVBoxLayout、QGridLayout、QFormLayout)實現一個基于對話框的綜合頁面。實現效果如圖 11-21 所示。實例代碼見 basiclayouts 實例。

圖 11-21 基本布局綜合實例效果圖
常用到的布局類有 QHBoxLayout、QVBoxLayout、QGridLayout、QFormLayout 這 4 種, 分別是水平布局、垂直布局、柵格布局和表單布局。布局中最常用的方法是 addWidget()和 addLayout(),addWidget()方法用于在布局中插入窗口部件,addLayout()用于在布局中插 入子布局。對于表單布局而言,向其中加入窗口部件最常用的方法是 addRow()。
下面通過實例的實現過程了解布局管理的使用方法。首先通過一個示意圖了解此對話 框的布局結構,如圖 11-22 所示。

圖 11-22 實例布局結構圖
從圖中可知,本實例共用到 4 個布局管理器,最外層也即是頂級布局是一個垂直布 局,它是 QVBoxLayout 的實例,在頂級布局里面的最上層是一個水平布局,它是 QHBoxLayout 的實例,在它的下面是一個柵格布局,它是 QGridLayout 的實例,然后下面是 一個表單布局,它是 QFormLayout 的實例。
下面是具體的實現,首先聲明一個對話框類 Dialog,它單繼承自 QDialog。在該類的 頭文件 dialog.h 中聲明對話框中的各個窗口部件。
```
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog();
private:
void createHorizontalGroupBox();
void createGridGroupBox();
void createFormGroupBox();
enum { NumGridRows = 3, NumButtons = 4 };
QGroupBox *horizontalGroupBox;
QGroupBox *gridGroupBox;
QGroupBox *formGroupBox;
QTextEdit *smallEditor;
QTextEdit *bigEditor;
QLabel *labels[NumGridRows];
QLineEdit *lineEdits[NumGridRows];
QPushButton *buttons[NumButtons];
QDialogButtonBox *buttonBox;
};
```
然后定義對話框中包含的窗口部件。我們看看類的構造函數。
```
Dialog::Dialog()
{
createHorizontalGroupBox();
createGridGroupBox();
createFormGroupBox();
bigEditor = new QTextEdit;
bigEditor->setPlainText(tr("This widget takes up all the remaining space "
"in the top-level layout."));
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
| QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(horizontalGroupBox);
mainLayout->addWidget(gridGroupBox);
mainLayout->addWidget(formGroupBox);
mainLayout->addWidget(bigEditor);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle(tr("Basic Layouts"));
}
```
第 3-5 行分別創建了 3 個組框-GroupBox,在它們的內部是 3 個布局。
第 6-7 行創建了創建了一個 QTextEdit 類的實例,并設置了它的顯示文本。
第 8 行創建了一個 QDialogButtonBox 的實例,其中包含【OK】和【Cancel】兩個按鈕。
第 9-10 行連接按鈕的信號和窗體的響應的槽。
第 11 行定義了窗體的頂級布局,它是一個 QVBoxLayout 的實例,是垂直布局。
第 12-16 行依次向頂級布局中加入窗口部件,注意使用 addWidget()方法的話,這些窗 口部件在布局中的排列順序與它們的加入順序是關聯的。
小貼士:如果你想對布局內的窗口部件排列順序和位置大小等屬性做出更為詳盡的控 制,可以考慮使用 insertWidget()方法來向布局中加入窗口部件。insertWidget()的原型 如下:
```
void QBoxLayout::insertWidget ( int index, QWidget * widget, int stretch = 0, Qt::Alignment alignment = 0 )
```
它為窗口部件 widget 指定了伸縮因子 stretch 和排列方向 alignment,以及在布局內 的順序 index,然后把它加入到布局中。如果 index 的值為負整數,則表示把它加入到順序 的最后面。
在布局中,哪個窗口部件的 stretch 值更大,那么它將有可能獲得更大的空間。 如果在布局里面,所有窗口部件的 stretch 值都為 0,或者都不超過 0,那么它們的大小將由各自的大小策略以及大小策略互相影響的關系決定。
alignment 指定了窗口部件的排列方向,默認值為 0,表示該窗口部件將占用整個布局 內部的區域。alignment 通常有 3 個方向的取值,依次如如表 11-7、表 11-8 和表 11-9 所 示。
表 11-7 水平方向的取值
| 常量 | 值 | 說明 |
| --- | --- | --- |
| Qt::AlignLeft | 0x0001 | 在布局內水平左對齊 |
| Qt::AlignRight | 0x0002 | 在布局內水平右對齊 |
| Qt::AlignHCenter | 0x0004 | 在可用的空間內部水平居中排列 |
| Qt::AlignJustify | 0x0008 | Justifies the text in the available space. |
注意,水平方向同時只能取一個值。
表 11-8 垂直方向的取值
| 常量 | 值 | 說明 |
| --- | --- | --- |
| Qt::AlignTop | 0x0020 | 在布局內垂直向上對齊 |
| Qt::AlignBottom | 0x0040 | 在布局內垂直向下對齊 |
| Qt::AlignVCenter | 0x0080 | 在可用的空間內部垂直居中排列 |
垂直方向同時也只能取一個值。
表 11-9 居中取值
| 常量 | 值 | 說明 |
| --- | --- | --- |
| Qt::AlignCenter | AlignVCenter | AlignHCenter | 在水平方向和垂直方向都居中排列 |
如果已近使用了居中取值的話,就不必再設置水平和垂直方向的取值了。
第 17 行將主布局安裝到窗體上。
第 18 行設置窗口標題。
再來看看創建水平布局的 createHorizontalGroupBox()函數。
```
void Dialog::createHorizontalGroupBox()
{
horizontalGroupBox = new QGroupBox(tr("Horizontal layout"));
QHBoxLayout *layout = new QHBoxLayout;
for (int i = 0; i < NumButtons; ++i)
{
buttons[i] = new QPushButton(tr("Button %1").arg(i + 1));
layout->addWidget(buttons[i]);
}
horizontalGroupBox->setLayout(layout);
}
```
第 4 行定義了一個水平布局的實例。
第 5-9 行定義了幾個按鈕窗口部件,然后依次向該布局中加入它們。
第 10 行把該布局安裝到它的父窗體上。 然后看看創建柵格布局的函數 createGridGroupBox()里面的內容。
```
void Dialog::createGridGroupBox()
{
gridGroupBox = new QGroupBox(tr("Grid layout"));
QGridLayout *layout = new QGridLayout;
for (int i = 0; i < NumGridRows; ++i)
{
labels[i] = new QLabel(tr("Line %1:").arg(i + 1));
lineEdits[i] = new QLineEdit;
layout->addWidget(labels[i], i + 1, 0);
layout->addWidget(lineEdits[i], i + 1, 1);
}
smallEditor = new QTextEdit;
smallEditor->setPlainText(tr("This widget takes up about two thirds of the "
"grid layout."));
layout->addWidget(smallEditor, 0, 2, 4, 1);
layout->setColumnStretch(1, 10);
layout->setColumnStretch(2, 20);
gridGroupBox->setLayout(layout);
}
```
第 1 行創建了一個組框的實例,它將作為柵格布局的父窗口。
第 3-9 行創建了若干 QLineEdit 的實例,并使用 addWidget()方法把它們加入到布局 中。addWidget()有若干變型,這里使用的這個需要依次指定窗口部件、行和列以及對齊方 式,對齊方式默認為 0。注意可以看到這里的第 1 個 QLineEdit 實例位于(1,0)這個單元 (cell)。
第 10-11 行創建一個 QTextEdit 實例,并為它設置顯示文本。
第 12 行將 QTextEdit 的實例 smallEditor 加入到布局中,這里使用的是 addWidget() 的另一種常用變型,其實參分別需要指定窗口部件、起始行、起始列、行跨度數和列跨度 數。
在本實例中實際上創建了一個 3x3 的柵格布局。左上角的文本為 Line 1 的標簽窗口部 件位于(1,0),這樣就可知道使用本行創建的 smallEditor 窗口部件位于(0,2),行跨度是 4 行,列跨度是 1 列,也就是它的單元占用了 4 行 1 列的空間。
第 13-14 行分別設置了第 1 列和第 2 列的伸縮因子為 10 和 20,這就保證了這兩列無論 何時均保持寬度為 1:2。
第 15 行把這個柵格布局安裝到其父窗口 gridGroupBox 上。 再看一下創建表單布局的 createFormGroupBox()函數內容。
```
void Dialog::createFormGroupBox()
{
formGroupBox = new QGroupBox(tr("Form layout"));
QFormLayout *layout = new QFormLayout;
layout->addRow(new QLabel(tr("Line 1:")), new QLineEdit);
layout->addRow(new QLabel(tr("Line 2, long text:")), new QComboBox);
layout->addRow(new QLabel(tr("Line 3:")), new QSpinBox);
formGroupBox->setLayout(layout);
}
```
第 1 行創建了一個組框,用于管理表單布局。
第 2 行創建了一個表單布局的實例。
第 3-5 行使用 addRow()方法,創建了幾個 QLabel 的實例和 QLineEdit、QComboBox 和 QSpinBox 的實例,并把它們加入到表單布局中。在前面講解表單布局的時候,曾經說到過 addRow()方法有很多種變型,此處采用的是其中的一種。
第 6 行把表單布局安裝到它的父窗口上,它的父窗口就是第 1 行創建的組框實例。 最后書寫主函數 main.cpp,其內容是創建應用程序全局實例,將剛才創建的窗口顯示出來。
```
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Dialog dialog;
return dialog.exec();
}
```
這個實例完全采用手寫代碼實現。可以自己書寫 .pro 文件,也可以在命令行下依次鍵 入 qmake 來生成。
本實例分析了 Qt4 中布局管理常用到的類及其方法,如果讀者覺得這種手動布局的方 法比較麻煩,也可采用 Qt Designer 來布局。
- 第 1 章 走近 Qt
- 1.1 Qt 簡介
- 1.2 Qt 紀事概覽
- 1.3 Qt 套件的組成(以 Qt4.5 為準)
- 1.4 Qt 的授權
- 1.5 Qt 的產品
- 1.6 Qt 的服務與支持
- 1.7 Qt 的最新進展
- 1.8為什么選擇 Qt
- 1.9 問題與解答
- 1.10 總結與提高
- 第 2 章 Qt 的安裝與配置
- 2.1 獲取 Qt
- 2.2 協議說明
- 2.3 安裝 Qt
- 2.4 配置 Qt4 環境
- 2.5 問題與解答
- 2.6 總結與提高
- 第 3 章 Qt 編程基礎
- 3.1 標準 C++精講
- 3.2 Windows 編程基礎
- 3.3 Linux 編程基礎
- 3.4 Mac 編程基礎
- 3.5 問題與解答
- 3.6 總結與提高
- 第 4 章 Qt 4 集成開發環境
- 4.1 常見的 Qt IDE
- 4.2 Qt Creator
- 4.3 Eclipse
- 4.5 問題與解答
- 4.6 總結與提高
- 第 5 章 使用 Qt 基本 GUI 工具
- 5.1 使用 Qt Designer 進行 GUI 設計
- 5.2 使用 Qt Assistant 獲取在線文檔與幫助
- 5.3 使用 Qt Demo 學習 Qt 應用程序開發
- 5.4 問題與解答
- 5.5 總結與提高
- 第 6 章 Qt 4 程序開發方法和流程
- 6.1 開發方法
- 6.2 Hello Qt
- 6.3 幾個重要的知識點
- 6.4 問題與解答
- 6.5 總結與提高
- 第 7 章 對話框
- 7.1 QDialog 類
- 7.2 子類化 QDialog
- 7.3 快速設計對話框
- 7.4 常見內建(built in)對話框的使用
- 7.5 模態對話框與非模態對話框
- 7.6 問題與解答
- 7.7 總結與提高
- 第 8 章 主窗口
- 8.1 主窗口框架
- 8.2 創建主窗口的方法和流程
- 8.3 代碼創建主窗口
- 8.4 使用 Qt Designer 創建主窗口
- 8.5 中心窗口部件專題
- 8.6 Qt4 資源系統專題
- 8.7 錨接窗口
- 8.8 多文檔
- 8.9 問題與解答
- 8.10 總結與提高
- 第 9 章 Qt 樣式表與應用程序觀感
- 9.1 應用程序的觀感
- 9.2 QStyle 類的使用
- 9.3 樣式表概述
- 9.4 使用樣式表
- 9.5 問題與解答
- 9.6 總結與提高
- 第 10 章 在程序中使用.ui 文件
- 10.1 uic 的使用
- 10.2 Ui_YourFormName.h 文件的組成
- 10.3 編譯時加入處理.ui 文件的方法
- 10.4 運行時加入處理.ui 文件的方法
- 10.5 信號與槽的自動連接
- 10.6 問題與解答
- 10.7 總結與提高 本章主要講解了以下內容:
- 第 11 章 布局管理
- 11.1 基本概念和方法
- 11.2在 Qt Designer 中使用布局
- 11.3 基本布局實踐
- 11.4 堆棧布局
- 11.5 分裂器布局
- 11.6 自定義布局管理器
- 11.7 布局管理經驗總結
- 11.8 問題與解答
- 11.9 總結與提高
- 第 12 章 使用 Qt Creator
- 12.1 Qt Creator 概覽
- 12.2 Qt Creator 的組成
- 12.3 快捷鍵和常用技巧
- 12.4 Qt Creator 構建系統的設置
- 12.5 處理項目間依賴關系( Dependencies )
- 12.6 Qt 多版本共存時的管理
- 12.7 使用定位器在代碼間快速導航
- 12.8 如何創建一個項目
- 12.9 實例講解
- 12.10 使用 Qt Creator 調試程序
- 12.11 問題與解答
- 12.12 總結與提高
- 第 13 章 Qt 核心機制與原理
- 13.1 Qt 對標準 C++的擴展
- 13.2 信號與槽
- 13.3 元對象系統
- 13.4 Qt 的架構
- 13.5 Qt 的事件模型
- 13.6 構建 Qt 應用程序
- 13.7 總結與提高
- 附錄 A qmake 使用指南
- A.1 qmake 簡介
- A.2 使用 qmake
- 附錄 B make 命令
- B.1 命令解釋
- B.2 使用 make 自動構建
- 附錄 C Qt 資源
- C.1Qt 官方資源
- C.2 Qt 開發社區