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

使用代碼的方式時我們拖拽窗口時,按鈕的位置也會隨著窗口的調整而改變。
我們還可以使用圖形化界面的方式來進行垂直布局:

但是注意使用圖形化界面的方式時我們拖拽窗口,按鈕的位置不會隨著窗口的調整而改變。
3 水平布局
使? QHBoxLayout 表?垂直的布局管理器,H 是 horizontal 的縮寫。
核?屬性 (和 QVBoxLayout 屬性是?致的)
| 屬性 | 說明 |
|---|---|
| layoutLeftMargin | 左側邊距 |
| layoutRightMargin | 右側邊距 |
| 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);
// 設置 layout 到 widget 上
this->setLayout(layout);
}
結果驗證:

同理我們也可以使用圖形化界面的方式來創(chuàng)建水平布局。這里就不再演示了。
4 網格布局
Qt 中還提供了 QGridLayout ?來實現(xiàn)?格布局的效果,可以達到 M * N 的這種?格的效果。
核?屬性:整體和 QVBoxLayout 以及 QHBoxLayout 相似,但是設置 spacing 的時候是按照垂直?平兩個?向來設置的。
| 屬性 | 說明 |
|---|---|
| layoutLeftMargin | 左側邊距 |
| layoutRightMargin | 右側邊距 |
| layoutTopMargin | 上?邊距 |
| layoutBottomMargin | 下?邊距 |
| layoutHorizontalSpacing | 相鄰元素之間?平?向的間距 |
| layoutVerticalSpacing | 相鄰元素之間垂直?向的間距 |
| layoutRowStretch | ??向的拉伸系數(shù) |
| layoutColumnStretch | 列?向的拉伸系數(shù) |
代碼?例:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 4 個按鈕
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);
// 設置 layout 到窗?中.
this->setLayout(layout);
}
結果驗證:

我們再來看看使用下面的代碼會出現(xiàn)什么情況:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 4 個按鈕
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);
// 設置 layout 到窗?中.
this->setLayout(layout);
}
結果驗證:

此處也要注意, 設置?和列的時候, 如果設置的是?個很?的值, 但是這個值和上?個值之間并沒有其他的元素, 那么并不會在中間騰出額外的空間。
代碼?例: 設置 QGridLayout 中元素的???例
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 6 個按鈕
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);
// 設置拉伸?例,設置為0的話為默認大小
// 第 0 列拉伸?例設為 3;
layout->setColumnStretch(0, 3);
// 第 1 列拉伸?例設為 2,
layout->setColumnStretch(1, 2);
// 第 2 列拉伸?例設為 1
layout->setColumnStretch(2, 1);
// 設置 layout 到窗?中.
this->setLayout(layout);
}
結果驗證:

另外, QGridLayout 也提供了 setRowStretch 設置?之間的拉伸系數(shù)。上述案例中, 直接設置 setRowStretch 效果不明顯, 因為每個按鈕的?度是固定的,需要把按鈕的垂直?向的 sizePolicy 屬性設置為 QSizePolicy::Expanding 盡可能填充滿布局管理器, 才能看到效果。
代碼?例: 設置垂直?向的拉伸系數(shù)。
使? setSizePolicy 設置按鈕的尺?策略,可選的值如下:
- QSizePolicy::Ignored : 忽略控件的尺?,不對布局產?影響。
- QSizePolicy::Minimum : 控件的最?尺?為固定值,布局時不會超過該值。
- QSizePolicy::Maximum : 控件的最?尺?為固定值,布局時不會?于該值。
- QSizePolicy::Preferred : 控件的理想尺?為固定值,布局時會盡量接近該值。
- QSizePolicy::Expanding : 控件的尺?可以根據(jù)空間調整,盡可能占據(jù)更多空間。
- QSizePolicy::Shrinking : 控件的尺?可以根據(jù)空間調整,盡可能縮?以適應空間。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 創(chuàng)建 6 個按鈕
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");
// 設置按鈕的 sizePolicy, 此時按鈕的?平?向和垂直?向都會盡量舒展開
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);
// 設置拉伸?例
// 第 0 ?拉伸?例設為 1;
layout->setRowStretch(0, 1);
// 第 1 ?拉伸?例設為 0, 即為固定??, 不參與拉伸
layout->setRowStretch(1, 0);
// 第 2 ?拉伸?例設為 2, 即為第 2 ?的寬度是第 0 ?的 2 倍
layout->setRowStretch(2, 2);
// 設置 layout 到窗?中.
this->setLayout(layout);
}
結果驗證:

5 表單布局
除了上述的布局管理器之外, Qt 還提供了 QFormLayout , 屬于是 QGridLayout 的特殊情況, 專??于實現(xiàn)兩列表單的布局。這種表單布局多?于讓??填寫信息的場景,左側列為提?, 右側列為輸?框。
代碼示例:
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)建三個 label
QLabel* label1 = new QLabel("姓名");
QLabel* label2 = new QLabel("年齡");
QLabel* label3 = new QLabel("電話");
// 創(chuàng)建三個 lineEdit
QLineEdit* lineEdit1 = new QLineEdit();
QLineEdit* lineEdit2 = new QLineEdit();
QLineEdit* lineEdit3 = new QLineEdit();
// 創(chuàng)建?個提交按鈕
QPushButton* btn = new QPushButton("提交");
// 把上述元素添加到 layout 中
layout->addRow(label1, lineEdit1);
layout->addRow(label2, lineEdit2);
layout->addRow(label3, lineEdit3);
layout->addRow(NULL, btn);
}
結果驗證:

以上就是一文詳解Qt如何優(yōu)雅的進行界面布局的詳細內容,更多關于Qt界面布局的資料請關注腳本之家其它相關文章!
相關文章
基于VC中使用ForceInclude來強制包含stdafx.h的解決方法
本篇文章是對VC中使用ForceInclude來強制包含stdafx.h的解決方法進行了詳細的分析介紹,需要的朋友參考下2013-05-05
C語言用循環(huán)單鏈表實現(xiàn)約瑟夫環(huán)
這篇文章主要為大家詳細介紹了C語言用循環(huán)單鏈表實現(xiàn)約瑟夫環(huán),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10

