一文詳解Qt如何優(yōu)雅的進(jìn)行界面布局
1 寫(xiě)在前面
之前使? Qt 在界?上創(chuàng)建的控件, 都是通過(guò) “絕對(duì)定位” 的?式來(lái)設(shè)定的。也就是每個(gè)控件所在的位置, 都需要計(jì)算坐標(biāo), 最終通過(guò) setGeometry 或者 move ?式擺放過(guò)去。
這種設(shè)定?式其實(shí)并不?便,尤其是界?如果內(nèi)容?較多, 不好計(jì)算。?且?個(gè)窗???往往是可以調(diào)整的, 按照絕對(duì)定位的?式, 也?法?適應(yīng)窗???。因此 Qt 引? 布局管理器 (Layout) 機(jī)制, 來(lái)解決上述問(wèn)題。
2 垂直布局
使? QVBoxLayout 表?垂直的布局管理器,V 是 vertical 的縮寫(xiě)。
核?屬性:
| 屬性 | 說(shuō)明 |
|---|---|
| layoutLeftMargin | 左側(cè)邊距 |
| layoutRightMargin | 右側(cè)邊距 |
| layoutTopMargin | 上?邊距 |
| layoutBottomMargin | 下?邊距 |
| layoutSpacing | 相鄰元素之間的間距 |
Layout 只是?于界?布局, 并沒(méi)有提供信號(hào)。
代碼示例:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* btn1 = new QPushButton("按鈕1");
QPushButton* btn2 = new QPushButton("按鈕2");
QPushButton* btn3 = new QPushButton("按鈕3");
// 創(chuàng)建布局管理器, 并且把按鈕添加進(jìn)去
// 如果創(chuàng)建的時(shí)候指定?元素為 this, 則后?不需要 setLayout ?法
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(btn1);
layout->addWidget(btn2);
layout->addWidget(btn3);
// 把布局管理器設(shè)置到 widget 中
this->setLayout(layout);
}
驗(yàn)證結(jié)果:

使用代碼的方式時(shí)我們拖拽窗口時(shí),按鈕的位置也會(huì)隨著窗口的調(diào)整而改變。
我們還可以使用圖形化界面的方式來(lái)進(jìn)行垂直布局:

但是注意使用圖形化界面的方式時(shí)我們拖拽窗口,按鈕的位置不會(huì)隨著窗口的調(diào)整而改變。
3 水平布局
使? QHBoxLayout 表?垂直的布局管理器,H 是 horizontal 的縮寫(xiě)。
核?屬性 (和 QVBoxLayout 屬性是?致的)
| 屬性 | 說(shuō)明 |
|---|---|
| layoutLeftMargin | 左側(cè)邊距 |
| layoutRightMargin | 右側(cè)邊距 |
| layoutTopMargin | 上?邊距 |
| layoutBottomMargin | 下?邊距 |
| layoutSpacing | 相鄰元素之間的間距 |
代碼?例:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* btn1 = new QPushButton("按鈕1");
QPushButton* btn2 = new QPushButton("按鈕2");
QPushButton* btn3 = new QPushButton("按鈕3");
// 創(chuàng)建布局管理器
QHBoxLayout* layout = new QHBoxLayout();
layout->addWidget(btn1);
layout->addWidget(btn2);
layout->addWidget(btn3);
// 設(shè)置 layout 到 widget 上
this->setLayout(layout);
}
結(jié)果驗(yàn)證:

同理我們也可以使用圖形化界面的方式來(lái)創(chuàng)建水平布局。這里就不再演示了。
4 網(wǎng)格布局
Qt 中還提供了 QGridLayout ?來(lái)實(shí)現(xiàn)?格布局的效果,可以達(dá)到 M * N 的這種?格的效果。
核?屬性:整體和 QVBoxLayout 以及 QHBoxLayout 相似,但是設(shè)置 spacing 的時(shí)候是按照垂直?平兩個(gè)?向來(lái)設(shè)置的。
| 屬性 | 說(shuō)明 |
|---|---|
| layoutLeftMargin | 左側(cè)邊距 |
| layoutRightMargin | 右側(cè)邊距 |
| layoutTopMargin | 上?邊距 |
| layoutBottomMargin | 下?邊距 |
| layoutHorizontalSpacing | 相鄰元素之間?平?向的間距 |
| layoutVerticalSpacing | 相鄰元素之間垂直?向的間距 |
| layoutRowStretch | ??向的拉伸系數(shù) |
| layoutColumnStretch | 列?向的拉伸系數(shù) |
代碼?例:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 4 個(gè)按鈕
QPushButton* btn1 = new QPushButton("按鈕1");
QPushButton* btn2 = new QPushButton("按鈕2");
QPushButton* btn3 = new QPushButton("按鈕3");
QPushButton* btn4 = new QPushButton("按鈕4");
// 創(chuàng)建?格布局管理器, 并且添加元素
QGridLayout* layout = new QGridLayout();
layout->addWidget(btn1, 0, 0);
layout->addWidget(btn2, 0, 2);
layout->addWidget(btn3, 1, 1);
layout->addWidget(btn4, 1, 3);
// 設(shè)置 layout 到窗?中.
this->setLayout(layout);
}
結(jié)果驗(yàn)證:

我們?cè)賮?lái)看看使用下面的代碼會(huì)出現(xiàn)什么情況:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 4 個(gè)按鈕
QPushButton* btn1 = new QPushButton("按鈕1");
QPushButton* btn2 = new QPushButton("按鈕2");
QPushButton* btn3 = new QPushButton("按鈕3");
QPushButton* btn4 = new QPushButton("按鈕4");
// 創(chuàng)建?格布局管理器, 并且添加元素
QGridLayout* layout = new QGridLayout();
layout->addWidget(btn1, 0, 0);
layout->addWidget(btn2, 1, 0);
layout->addWidget(btn3, 2, 0);
layout->addWidget(btn4, 5, 0);
// 設(shè)置 layout 到窗?中.
this->setLayout(layout);
}
結(jié)果驗(yàn)證:

此處也要注意, 設(shè)置?和列的時(shí)候, 如果設(shè)置的是?個(gè)很?的值, 但是這個(gè)值和上?個(gè)值之間并沒(méi)有其他的元素, 那么并不會(huì)在中間騰出額外的空間。
代碼?例: 設(shè)置 QGridLayout 中元素的???例
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 6 個(gè)按鈕
QPushButton* btn1 = new QPushButton("按鈕1");
QPushButton* btn2 = new QPushButton("按鈕2");
QPushButton* btn3 = new QPushButton("按鈕3");
QPushButton* btn4 = new QPushButton("按鈕4");
QPushButton* btn5 = new QPushButton("按鈕5");
QPushButton* btn6 = new QPushButton("按鈕6");
// 創(chuàng)建?格布局管理器, 并且添加元素
QGridLayout* layout = new QGridLayout();
layout->addWidget(btn1, 0, 0);
layout->addWidget(btn2, 0, 1);
layout->addWidget(btn3, 0, 2);
layout->addWidget(btn4, 1, 0);
layout->addWidget(btn5, 1, 1);
layout->addWidget(btn6, 1, 2);
// 設(shè)置拉伸?例,設(shè)置為0的話(huà)為默認(rèn)大小
// 第 0 列拉伸?例設(shè)為 3;
layout->setColumnStretch(0, 3);
// 第 1 列拉伸?例設(shè)為 2,
layout->setColumnStretch(1, 2);
// 第 2 列拉伸?例設(shè)為 1
layout->setColumnStretch(2, 1);
// 設(shè)置 layout 到窗?中.
this->setLayout(layout);
}
結(jié)果驗(yàn)證:

另外, QGridLayout 也提供了 setRowStretch 設(shè)置?之間的拉伸系數(shù)。上述案例中, 直接設(shè)置 setRowStretch 效果不明顯, 因?yàn)槊總€(gè)按鈕的?度是固定的,需要把按鈕的垂直?向的 sizePolicy 屬性設(shè)置為 QSizePolicy::Expanding 盡可能填充滿(mǎn)布局管理器, 才能看到效果。
代碼?例: 設(shè)置垂直?向的拉伸系數(shù)。
使? setSizePolicy 設(shè)置按鈕的尺?策略,可選的值如下:
- QSizePolicy::Ignored : 忽略控件的尺?,不對(duì)布局產(chǎn)?影響。
- QSizePolicy::Minimum : 控件的最?尺?為固定值,布局時(shí)不會(huì)超過(guò)該值。
- QSizePolicy::Maximum : 控件的最?尺?為固定值,布局時(shí)不會(huì)?于該值。
- QSizePolicy::Preferred : 控件的理想尺?為固定值,布局時(shí)會(huì)盡量接近該值。
- QSizePolicy::Expanding : 控件的尺?可以根據(jù)空間調(diào)整,盡可能占據(jù)更多空間。
- QSizePolicy::Shrinking : 控件的尺?可以根據(jù)空間調(diào)整,盡可能縮?以適應(yīng)空間。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 6 個(gè)按鈕
QPushButton* btn1 = new QPushButton("按鈕1");
QPushButton* btn2 = new QPushButton("按鈕2");
QPushButton* btn3 = new QPushButton("按鈕3");
QPushButton* btn4 = new QPushButton("按鈕4");
QPushButton* btn5 = new QPushButton("按鈕5");
QPushButton* btn6 = new QPushButton("按鈕6");
// 設(shè)置按鈕的 sizePolicy, 此時(shí)按鈕的?平?向和垂直?向都會(huì)盡量舒展開(kāi)
btn1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
btn2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
btn3->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
btn4->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
btn5->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
btn6->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
// 創(chuàng)建?格布局管理器, 并且添加元素
QGridLayout* layout = new QGridLayout();
layout->addWidget(btn1, 0, 0);
layout->addWidget(btn2, 0, 1);
layout->addWidget(btn3, 1, 0);
layout->addWidget(btn4, 1, 1);
layout->addWidget(btn5, 2, 0);
layout->addWidget(btn6, 2, 1);
// 設(shè)置拉伸?例
// 第 0 ?拉伸?例設(shè)為 1;
layout->setRowStretch(0, 1);
// 第 1 ?拉伸?例設(shè)為 0, 即為固定??, 不參與拉伸
layout->setRowStretch(1, 0);
// 第 2 ?拉伸?例設(shè)為 2, 即為第 2 ?的寬度是第 0 ?的 2 倍
layout->setRowStretch(2, 2);
// 設(shè)置 layout 到窗?中.
this->setLayout(layout);
}
結(jié)果驗(yàn)證:

5 表單布局
除了上述的布局管理器之外, Qt 還提供了 QFormLayout , 屬于是 QGridLayout 的特殊情況, 專(zhuān)??于實(shí)現(xiàn)兩列表單的布局。這種表單布局多?于讓??填寫(xiě)信息的場(chǎng)景,左側(cè)列為提?, 右側(cè)列為輸?框。
代碼示例:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 layout
QFormLayout* layout = new QFormLayout();
this->setLayout(layout);
// 創(chuàng)建三個(gè) label
QLabel* label1 = new QLabel("姓名");
QLabel* label2 = new QLabel("年齡");
QLabel* label3 = new QLabel("電話(huà)");
// 創(chuàng)建三個(gè) lineEdit
QLineEdit* lineEdit1 = new QLineEdit();
QLineEdit* lineEdit2 = new QLineEdit();
QLineEdit* lineEdit3 = new QLineEdit();
// 創(chuàng)建?個(gè)提交按鈕
QPushButton* btn = new QPushButton("提交");
// 把上述元素添加到 layout 中
layout->addRow(label1, lineEdit1);
layout->addRow(label2, lineEdit2);
layout->addRow(label3, lineEdit3);
layout->addRow(NULL, btn);
}
結(jié)果驗(yàn)證:

以上就是一文詳解Qt如何優(yōu)雅的進(jìn)行界面布局的詳細(xì)內(nèi)容,更多關(guān)于Qt界面布局的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于VC中使用ForceInclude來(lái)強(qiáng)制包含stdafx.h的解決方法
本篇文章是對(duì)VC中使用ForceInclude來(lái)強(qiáng)制包含stdafx.h的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C++中多線(xiàn)程的執(zhí)行順序如你預(yù)期嗎
這篇文章主要為大家詳細(xì)介紹一下C++中多線(xiàn)程的執(zhí)行順序的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++多線(xiàn)程有一定幫助,需要的可以參考一下2022-10-10
C/C++高精度運(yùn)算(大整數(shù)運(yùn)算)詳細(xì)講解
高精度算法的本質(zhì)是把大數(shù)拆成若干固定長(zhǎng)度的塊,然后對(duì)每一塊進(jìn)行相應(yīng)的運(yùn)算,下面這篇文章主要給大家介紹了關(guān)于C/C++高精度運(yùn)算(大整數(shù)運(yùn)算)的相關(guān)資料,需要的朋友可以參考下2022-11-11
C語(yǔ)言用循環(huán)單鏈表實(shí)現(xiàn)約瑟夫環(huán)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言用循環(huán)單鏈表實(shí)現(xiàn)約瑟夫環(huán),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
詳解C語(yǔ)言中scanf函數(shù)使用的一些注意點(diǎn)
這篇文章主要介紹了C語(yǔ)言中scanf函數(shù)使用的一些注意點(diǎn),scanf函數(shù)的使用是C語(yǔ)言入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-04-04
一起來(lái)學(xué)習(xí)C語(yǔ)言的字符串轉(zhuǎn)換函數(shù)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的字符串轉(zhuǎn)換函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02

