Qt-5种布局控件详解
實際開發中,一個界面上可能包含十幾個控件,手動調整它們的位置既費時又費力。作為一款成熟的 GUI 框架,Qt 提供了很多擺放控件的輔助工具(又稱布局管理器或者布局控件),它們可以完成兩件事:
- 自動調整控件的位置,包括控件之間的間距、對齊等;
- 當用戶調整窗口大小時,位于布局管理器內的控件也會隨之調整大小,從而保持整個界面的美觀。
總之借助布局管理器,我們無需再逐個調整控件的位置和大小,可以將更多的精力放在軟件功能的實現上。
Qt 共提供了 5 種布局管理器,每種布局管理器對應一個類,分別是 QVBoxLayout(垂直布局)、QHBoxLayout(水平布局)、QGridLayout(網格布局)、QFormLayout(表單布局)和 QStackedLayout(分組布局),它們的繼承關系如下圖所示:
?
圖 1 各個布局管理類的繼承關系
QVBoxLayout垂直布局
垂直布局指的是將所有控件從上到下(或者從下到上)依次擺放,例如:
?
圖 2 QVBoxLayout垂直布局
圖 2 展示了 4 個 QPushButton 按鈕利用 QVBoxLayout 垂直布局的效果。實際場景中,QVBoxLayout 中還可以放置其它控件,比如 QLabel 文本框、QLineEdit 單行輸入框等。
程序中使用 QVBoxLayout 布局控件,需提前引入<QVBoxLayout>頭文件。每個 QVBoxLayout 控件本質都是 QVBoxLayout 類的實例對象,該類提供了兩個構造函數,分別是:
創建 QVBoxLayout 控件的同時可以指定父窗口,那么它將作為父窗口中管理其它控件的工具;也可以暫時不指定父窗口,待全部設置完畢后再將其添加到某個窗口中。
QVBoxLayout 類沒有新增任何成員方法,它只能使用從父類繼承的成員方法,下表給大家羅列了常用的一些:
?
| void QBoxLayout::addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = Qt::Alignment()) | 向布局管理器中添加指定的 widget 控件。 默認情況下,stretch 拉伸系數為 0,表示 widget 控件的尺寸為默認值;alignment 是一個枚舉類型參數,默認值也是 0,表示該控件會填滿占用的整個空間。 |
| void QBoxLayout::addStretch(int stretch = 0) | 添加一個空白行,整個窗口中除了控件占用的區域外,其它區域可以由多個(≥0)空白行分攤,分攤比例取余于各個空白行設置的 stretch 參數的值。 strech 參數的默認值為 0,表示當窗口很小時,空白行可以不占據窗口空間。當窗口中包含多個 strech 值為 0 的空白行時,它們會平分窗口中的空白區域。 |
| void QBoxLayout::addSpacing(int size) | 添加一個 size 大小的固定間距。 |
| void QLayout::setMargin(int margin) | 設置布局管理器中所有控件的外邊距,上、下、左、右外邊距的大小都為 margin。默認情況下,所有方向的外邊距為 11 px。 |
| void QLayout::setContentsMargins(int left, int top, int right, int bottom) | 設置布局管理器中所有控件的外邊距,和 setMargin() 的區別是,此方法可以自定義上、下、左、右外邊距的值。 |
| void QBoxLayout::setDirection(Direction direction) | 設置布局管理器中控件的布局方向,Direction 是一個枚舉類型,對于 QVBoxLayout 布局管理器,direction 參數的值通常選擇?QBoxLayout::TopToBottom(從上到下依次擺放)或者?QBoxLayout::BottomToTop(從下到上依次擺放)。 |
| bool QBoxLayout::setStretchFactor(QWidget *widget, int stretch) | 設置布局管理器中某個控件的拉伸系數。 |
| bool QBoxLayout::setStretchFactor(QLayout *layout, int stretch) | 布局管理器內部可以再放置一個布局管理器,該方法用來設置內部某個布局管理器的拉伸系數。 |
舉個簡單的例子:
程序中做了以下幾個操作:
- 通過調用 setDirection() 方法,將添加到 QVBoxLayout 管理器中的所有控件(包括空白行)按照從下到上的順序依次擺放。舉個例子,由于 lab1 文本框是第二個添加到管理器中的,因此在最終顯示的界面中,lab1 位于倒數第二的位置。
- 通過調用 addStrech() 方法,向管理器中先后添加了兩個空白行,它們的伸縮系數分別為 2 和 3,因此 widget 窗口中的空白區域會平均分為 5 份,一個空白行占?3 份,另一個占 2 份。
- 通過調用 addWidget() 方法,向管理器中先后添加了 3 個文本框,它們的拉伸系數比為 1:2:3,所以當我們拉伸 widget 窗口時,三個文本框的大小(寬度)呈現 1:2:3 的關系。
- 通過調用 setLayout() 方法,成功地將?layout 布局管理器添加到了 widget 窗口中。當然,也可以在創建 layout 對象時指定 widget 作為它的父窗口,兩種方式是完全等價的。
執行結果為:
圖 3 QVBoxLayout 實例演示
QHBoxLayout水平布局
水平布局指的是將所有控件從左到右(或者從右到左)依次擺放,例如:
?
圖 4 QHBoxLayout水平布局
使用 QHBoxLayout 水平布局控件,程序中要提前引入<QHBoxLayout>頭文件。QHBoxLayout 和 QVBoxLayout 繼承自同一個類,它們的用法非常相似,比如 QHBoxLayout 類也提供了兩個構造函數:
QHBoxLayout 類也沒有新添任何成員方法,它只能使用從父類繼承的成員方法。因此,表 1 中羅列的所有成員方法也同樣適用于 QHBoxLayout 對象。
注意,當 QHBoxLayout 對象調用表 1 中的 addStretch() 方法時,表示添加一個空白列。
舉個簡單的例子:
程序執行結果為:
圖 5 QHBoxLayout水平布局實例
圖 5 中,最左側和最右側各添加了一個空白列,它們的伸縮比例為 3:2,即它們的寬度比為 3:2。
QGridLayout網格布局
網格布局又稱格柵布局或者表格布局,指的是將一些控件按照行和列排列在窗口上,例如:
?
圖 6 QGridLayout網格布局
QGridLayout 的行標和列標都從 0 開始,例如圖 6 中 one 按鈕的位置為 (0, 0),Four 按鈕的位置為 (2, 0)。我們可以隨意指定 QGridLayout 的行數和列數,各個控件可以隨意擺放,必要時某些位置可以空著不用。
使用 QGridLayout 網格控件,程序中需引入<QGridLayout>頭文件。每個 QGridLayout 控件都是 QGridLayout 類的一個實例對象,該類提供了兩個構造函數,分別是:
QGridLayout 類提供了很多實用的成員方法,常用的如下表所示:
| int QGridLayout::rowCount() const | 獲取網格的行數。 |
| int QGridLayout::columnCount() const | 獲取網格的列數。 |
| void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment = Qt::Alignment()) | 將 widget 控件添加到網格中的?(row,column) 位置處,并且可以自定義該控件的對齊方式。 |
| void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment()) | 將 widget 控件從 (fromRow, fromColumn)?位置開始,跨 rowSpan 行和 ColumnSpan 列添加到網格中,并且可以自定義該控件的對齊方式。 |
| void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment = Qt::Alignment()) | 向網格中的 (row, column) 位置處添加 layout 布局管理器。 |
| void QGridLayout::addLayout(QLayout *layout, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment()) | 將 layout 布局管理器從??(row, column) 位置開始,跨 rowSpan 行和 ColumnSpan 列添加到網格中,并且可以自定義該布局控件的對齊方式。 |
| void QGridLayout::setColumnStretch(int column, int stretch) | 給指定的第 column 列設置伸縮系數。 |
| void QGridLayout::setRowStretch(int row, int stretch) | 給指定的第 row 行設置伸縮系數。 |
| void QGridLayout::setColumnMinimumWidth(int column, int minSize) | 設置第 column 列的最小寬度。 |
| void QGridLayout::setRowMinimumHeight(int row, int minSize) | 設置第 row 行的最小寬度。 |
舉個簡單的例子:
程序運行結果為:
圖 7 QGridLayout網格布局實例
圖 7 中,文本框控件從 (1,0) 位置開始,占據了 3 行 3 列的表格空間。
QFormLayout表單布局
Qt 提供了很多種輸入框控件,包括 QLineEdit 單行輸入框、QTextEdit 多行輸入框等。通常情況下,每個輸入框的旁邊都會附帶一些文字(又稱標簽),用來提示用戶需要輸入的信息。例如,圖 8 中第一個輸入框的標簽為 "Name",提示用戶填寫自己的姓名。
?
圖 8 QFromLayout表單布局
生成圖 8 這樣的界面,實現的方法有很多,例如:
第 1 種方法最大的弊端在于,各個控件的尺寸都是固定的,不會隨著父窗口尺寸的改變而改變。第 2、3、4 種方法都是借助布局控件實現的,各個控件的尺寸可以自動調整,但前兩種方法需要手動設置每一列的 strech 拉伸系數,而第 4 種方式不需要。總之對于生成類似圖 8 這樣的表單窗口,建議大家使用 QFormLayout 控件,因為使用 QFormLayout 編寫的代碼量最少,開發效率最高。?
QFormLayout 可以容納很多個輸入框以及對應的標簽,并將它們從上到下依次排列在界面上(如圖 8 所示)。大多數情況下,QFormLayout 底層是用 QGridLayout 網格布局管理器實現的,和后者不同的是,QFormLayout 只包含 2 列(不限制行數),且第一列放置標簽,第二列放置輸入框。
使用 QFormLayout 布局控件之前,程序中應引入<QFormLayout>頭文件。每一個表單布局控件都是 QFormLayout 類的一個實例對象,該類僅提供了一個構造函數:
- QFormLayout(QWidget *parent = Q_NULLPTR)
下表給大家羅列了操作 QFormLayout 對象常用的一些成員方法:
?
| void QFormLayout::addRow(QWidget *label, QWidget *field) | 將指定的 field 控件和存儲標簽的?label 控件添加到表單控件中的末尾。? |
| void QFormLayout::addRow(const QString &labelText, QWidget *field) | 將指定的 field 控件和 labelText 標簽添加到表單控件的末尾。 |
| void QFormLayout::insertRow(int row, const QString &labelText, QWidget *field) | 將指定的 field 控件和 labelText 標簽插入到表單控件中指定行的位置。 |
| void QFormLayout::removeRow(int row) | 刪除表單控件中的指定行。 |
| void QFormLayout::removeRow(QWidget *widget) | 刪除表單控件中 widget 控件所在的行。 |
| void setRowWrapPolicy(RowWrapPolicy policy) | 設置標簽的顯示格式,默認標簽位于控件的左側。 RowWrapPolicy 是 QFormLayout 中定義的枚舉類型,該類型包含 3 個值:
|
| void QFormLayout::setSpacing(int spacing) | 將行間距和列間距設置為 spacing。 |
舉個簡單的例子:
程序運行結果為:
圖 9 QFormLayout表單布局實例
QStackedLayout分組布局
QStackedLayout 布局管理器可以容納多個控件或者窗口,但每次只顯示其中的一個。
舉個簡單的例子,下圖中的界面就使用了 QStackedLayout 布局管理器:
圖 10 QStackedLayout布局管理器
整個窗口被一分為二,左側是 QListWidget 列表控件,右側是 QStackedLayout 布局管理器。QStackedLayout 中包含 QPushButonn、QLabel 和 QLineEdit 這 3 個控件,但每次只能 3 個控件中的一個。
QStackedLayout 自身無法切換當前顯示的控件或窗口,實際應用時通常和 QListWidget 或者 QComboBox 搭配使用。
使用 QStackedLayout 布局控件,程序中必須先引入<QStackedLayout>頭文件。 每個 QStackedLayout 控件都是 QStackedLayout 類的一個實例對象,該類提供有 3 個構造函數,分別是:
借助第二個構造函數,我們可以將 QStackedLayout 添加到指定的 parent 窗口中;借助第三個構造函數,我們可以將 QStackedLayout 嵌入到指定的?parentLayout 布局控件中
本節學習的 5 種布局控件都可以嵌套使用,例如將 QVBoxLayout 放到 QHBoxLayout 內部、將 QGridLayout 放到 QStackedLayout 內部等。
下表羅列了操作 QStackedLayout 對象常用的一些成員方法:
| int QStackedLayout::addWidget(QWidget *widget) | 將 widget 控件添加到 QStackedLayout 控件中。 |
| int QStackedLayout::insertWidget(int index, QWidget *widget) | 將 widget 控件插入到 QStackedLayout?控件指定的位置處。 |
| void QStackedLayout::currentChanged(int index) | 切換當前顯示的控件時,會觸發此信號,index 為顯示的新控件的索引。 |
| void QStackedLayout::widgetRemoved(int index) | 移除某個控件時,會觸發此信號,index 為被移除控件的索引。 |
| void setCurrentIndex(int index) | 將第 index 個控件作為要顯示的控件。 |
| void QStackedLayout::setCurrentWidget(QWidget *widget) | 設置 widget 作為當前要實現的控件。注意,必須保證 widget 存儲在 QStackedLayout 控件中。 |
這里我們以圖 10 所示的窗口為例,實現代碼如下:
此程序中,我們在 QHBoxLayout 水平布局控件內又放置了一個 QStackedLayout 分組布局控件。感興趣的讀者可以編寫程序,測試其它布局控件之間嵌套的效果。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Qt-5种布局控件详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决: /bin/sh: 1: jav
- 下一篇: Qt-手动布局