Qt布局器详解:从基础到高级的全面指南
Qt布局器详解:从基础到高级的全面指南
Qt布局管理器是Qt框架中用于管理用户界面组件位置和大小的重要工具。它提供了多种布局方式,包括水平布局、垂直布局、网格布局等,能够帮助开发者创建灵活且响应式的用户界面。本文将详细介绍Qt中各种布局管理器的概念、特点和使用方法。
布局管理器概念
布局是一种优雅而灵活的方式,可以在其容器中自动排列子小部件。每个小部件通过 sizeHint
和 sizePolicy
属性向布局报告其大小要求,布局相应地分配可用空间。
Qt 共提供了5 种布局管理器,每种布局管理器对应一个类,分别是 QHBoxLayout
(水平布局)、QVBoxLayout
(垂直布局)、QGridLayout
(网格布局)、QFormLayout
(表单布局)和 QStackedLayout
(分组布局),这些类直接或间接都是由QLayout
派生过来的,关系如下:
布局管理器不是界面组件,而是界面组件的定位策略。它们也相当于是一个容器,可以将任意容器类型的组件或者布局放在布局管理器中。
常见的布局管理器及特点
布局 | 类名 | 特点 |
---|---|---|
水平布局 | QHBoxLayout | 水平方向排列控件 |
垂直布局 | QVBoxLayout | 垂直方向排列控件 |
网格布局 | QGridLayout | 类似 Excel,使用行列管理控件 |
表单布局 | QFormLayout | 左侧是标签,右侧是输入框,适用于表单界面 |
自由布局 | QStackedLayout | 叠放多个控件,每次只显示一个 |
绝对布局 | setGeometry() | 手动设置控件的绝对位置(不推荐) |
特点
- 只要使用了布局管理器,控件的大小位置不能再修改,如果要调整控件大小通过策略,最大值,最小值调整,添加辅助控件。
- 布局管理器除了可以组件进行布局以外,还有一个重要的用途,就是使得组件随着窗口的大小变化而变化。
- 分裂器水平布局和分裂器垂直布局,跟水平布局和垂直布局最大的区别:使用分裂器进行布局时,组件随分裂器可以改变大小
布局有关的选项及对应关系
QHBoxLayout
水平布局
控件从左到右排列。窗口变大时,控件会自动扩展。
QPushButton *btn1 = new QPushButton("按钮 1");
QPushButton *btn2 = new QPushButton("按钮 2");
QHBoxLayout *layout = new QHBoxLayout; // 水平布局
layout->addWidget(btn1);//按钮添加到布局管理器中
layout->addWidget(btn2);
w.setLayout(layout);//设置当前界面(widget)的布局管理器
w.show();
QVBoxLayout
垂直布局
所有控件从上到下排列,适用于侧边栏、按钮组等。
QVBoxLayout *layout = new QVBoxLayout; // 垂直布局
layout->addWidget(new QPushButton("按钮 1"));
layout->addWidget(new QPushButton("按钮 2"));
layout->addWidget(new QPushButton("按钮 3"));
QWidget *window = new QWidget;
window->setLayout(layout);
window->show();
QGridLayout
网格布局
将控件放置到网格中布局,它本身会从父窗口或父布局中占据尽可能多的界面空间,然后把自己的空间划分为行和列,再把每个控件塞到设置好的一个或多个单元格中。通常情况下 QGridLayout
不需要自己添加空白条 QSpacerItem
,因为其他功能控件把各自的单元格占据之后,剩下没控件占据的单元格自然就是空的,空的格子默认里面什么都没有,也没有空白条。
QGridLayout *layout = new QGridLayout();
layout->addWidget(new QPushButton("按钮 1"), 0, 0); // (行, 列)
layout->addWidget(new QPushButton("按钮 2"), 0, 1);
layout->addWidget(new QPushButton("按钮 3"), 1, 0);
layout->addWidget(new QPushButton("按钮 4"), 1, 1);
window.setLayout(layout);
此种布局方式无法随着窗口大小而动态改变大小,给窗口设置网格布局即可。
QFormLayout
表单布局
常用于登录界面、设置窗口,左侧是标签,右侧是输入框。
QFormLayout *layout = new QFormLayout;
layout->addRow("姓名:", new QLineEdit);
layout->addRow("密码:", new QLineEdit);
layout->addRow(new QPushButton("登录"));
QWidget *window = new QWidget;
window->setLayout(layout);
window->show();
QT 高级布局器
Qt中的高级布局管理器,包括QStackedLayout
、QDockWidget
和QSplitter
,接下来我们一个·一个学习。
QStackedLayout
堆叠布局
QStackedLayout
是一种布局管理器,它允许在同一区域显示多个QWidget,并在它们之间进行切换。在QStackedLayout
中,只有一个QWidget可见,其他QWidget被隐藏。可以使用setCurrentIndex()
或setCurrentWidget()
函数在QWidget之间进行切换。
- 通过索引或控件指针切换页面
- 适用于向导界面(Wizard)、选项卡界面(Tab)、动画切换界面。
#include <QApplication>
#include <QStackedLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.setWindowTitle("QStackedLayout测试");
QStackedLayout slay;
QVBoxLayout vlay(&w);
QPushButton *bt = new QPushButton("切换");
vlay.addWidget(bt);
vlay.addLayout(&slay);
slay.addWidget(new QLabel("第一个窗口"));
slay.addWidget(new QLabel("第二个窗口"));
slay.addWidget(new QLabel("第三个窗口"));
slay.addWidget(new QLabel("第四个窗口"));
QObject::connect(bt, &QPushButton::clicked, [&]()->void{
int curr = slay.currentIndex();
curr++;
if(curr>=slay.count()) curr=0;
slay.setCurrentIndex(curr);
});
w.show();
return a.exec();
}
QDockWidget
停靠布局
QDockWidget
是 Qt 提供的一种可停靠(Dockable)窗口组件,它可以作为主窗口(QMainWindow)的子窗口,可以拖动、停靠到不同的区域,甚至可以浮动到外部窗口。QDockWidget由一个标题栏和一个可停靠的QWidget组成,标题栏包括一个关闭按钮和一个可停靠按钮。
#include <QApplication>
#include <QMainWindow>
#include <QDockWidget>
#include <QTextEdit>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QMainWindow mainWindow;
mainWindow.setWindowTitle("QDockWidget 示例");
// 创建中心部件(必须设置,否则主窗口无法停靠)
QTextEdit *textEdit = new QTextEdit(&mainWindow);
mainWindow.setCentralWidget(textEdit);
// 创建可停靠窗口
QDockWidget *dockWidget = new QDockWidget("停靠窗口", &mainWindow);
dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
// 停靠窗口内放置控件
QTextEdit *dockTextEdit = new QTextEdit();
dockWidget->setWidget(dockTextEdit);
// 将 QDockWidget 添加到主窗口
mainWindow.addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
mainWindow.resize(800, 600);
mainWindow.show();
return app.exec();
}
分裂器(QSplitter)
QSplitter(分裂器)
是Qt 提供的一种特殊布局管理方式
,它允许用户通过拖动分隔条来动态调整控件大小。它与QHBoxLayout(水平布局)
和QVBoxLayout(垂直布局)
的主要区别在于:
- 普通布局(QHBoxLayout/QVBoxLayout):控件的大小通常是自动分配的,不能手动调整大小。
- 分裂器布局(QSplitter):控件可以通过拖动分隔条来手动调整大小,提供更灵活的 UI 体验。
- 可以通过
setStretchFactor()
函数来设置子控件的拉伸系数,从而实现动态调整布局。使用属性中的handleWidth
可调节组件之间的间距。属性中的opaqueResize
默认情况下(打勾),使用鼠标拖动分割子窗口间的边界时,子窗口会动态的改变其大小。然而,如果希望在松开鼠标时才改变其大小,可以设置下面的参数,取消其勾选状态即可
Spacers (空间间隔器/弹簧)
QSpacerItem
主要用于在控件之间创建“空白空间”,可以:
- 推挤控件,让它们靠左、靠右、居中或对齐底部。
- 填充空白区域,保持界面美观。
- 在窗口大小调整时,动态改变大小,以适应不同的屏幕尺寸。
布局常用方法总结
设置控件比例
像Vertical Layouts(垂直布局)、Horizontal Layouts(水平布局)、Grid Layouts(网络布局)、Form Layouts(窗体布局)可以在这个地方设置控件之间的比例
设置控件大小策略
代码中实现如下
btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);