文章目录
- 一、前言
- 二、Widget与Layout
- 2.1、Widget(窗口部件)
- 2.2、Layout(布局)
- 三、应用
- 3.1、widget容器添加控件并布局
- 3.2、自适应布局示例
- 3.3、 垂直布局2:1分割布局
- 3.3.1、方法1——控件大小策略
- 3.3.2、方法2——布局setStretch方法
- 3.3.3、方法3—— 布局addWidget方法
- 3.3.4、方法4——QSplitter与布局结合
一、前言
- 在Qt中,“layout”(布局)和"widget"(窗口部件)是两个相关但不同的概念。QWidget本身可以作为一个容器来容纳其他控件,而布局管理器则可以在这些容器中安排控件的位置。
- 大小策略和stretch属性在Qt中都是非常有用的布局管理工具,可以帮助开发者精确地控制界面元素在布局中的大小和分布。大小策略主要用于定义控件自身的最小和最大尺寸行为,而stretch属性则用于在布局管理器中定义控件相对于其他控件的拉伸优先级,以实现动态的布局调整和分配。
二、Widget与Layout
2.1、Widget(窗口部件)
- 基本介绍
- Widget是Qt中用户界面的基本构建块,是所有可见的用户界面元素的基类。
- QWidget是QWidget类及其子类的实例,它们可以包含其他控件和部件,并且可以响应用户交互。常见的QWidget子类包括QPushButton、QLineEdit、QLabel等,它们用于显示和接收用户的输入或指示信息。
- 每个QWidget通常都会有一个父窗口,可以通过构造函数参数或者后续设置来指定。
- Widget 是Qt中用于构建用户界面的基本元素,QWidget即可作为控件也可以作为容器,作为容器的QWidget也可以像QDialog一样作为弹框。
- 布局相关
- 控件的大小策略(Size Policies)
- QSizePolicy::Fixed:固定大小,控件将保持其固定大小,不会随窗口大小改变而改变。
- QSizePolicy::Preferred:优先大小,控件希望保持其首选大小,但可以根据布局管理器的需要进行调整。
- QSizePolicy::Expanding:扩展大小,控件希望占用尽可能多的空间,可以随窗口的扩展而扩展。
- QSizePolicy::Minimum 和 QSizePolicy::Maximum:最小和最大大小,控件将尽可能保持在指定的最小和最大尺寸范围内。
// 创建一个子控件,例如QWidgets或其他需要放入布局中的控件
QWidget *widget1 = new QWidget(&window);
// 设置子控件的大小策略
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
widget1->setSizePolicy(sizePolicy); // 第一个控件占据更多空间
- 布局的Stretch属性
在布局管理器中,可以使用stretch属性来进一步控制控件在布局中的分配。Stretch属性定义了控件在布局中相对于其他控件拉伸的程度。当父布局容器的大小改变时,布局管理器根据各个控件的stretch属性决定如何分配额外的空间。
//(1)QHBoxLayout 和 QVBoxLayout 中的Stretch
QHBoxLayout *hLayout = new QHBoxLayout;
QPushButton *button1 = new QPushButton("Button 1");
QPushButton *button2 = new QPushButton("Button 2");
hLayout->addWidget(button1, 1); // 指定按钮1的stretch为1
hLayout->addWidget(button2, 2); // 指定按钮2的stretch为2
//在布局容器改变大小时,按钮2会获得比按钮1更多的额外空间。
//(2)QGridLayout 中的Stretch
//在网格布局(QGridLayout)中,可以使用 setRowStretch() 和 setColumnStretch() 方法来设置行或列的stretch属性
QGridLayout *gridLayout = new QGridLayout;
gridLayout->addWidget(button1, 0, 0);
gridLayout->addWidget(button2, 0, 1);
gridLayout->setColumnStretch(0, 1); // 设置第0列的stretch为1
gridLayout->setColumnStretch(1, 2); // 设置第1列的stretch为2
2.2、Layout(布局)
- 基本介绍
- Layout是一种机制,用于管理一个或多个Widget在父Widget(通常是窗口或者另一个Widget)中的位置和大小。
- 布局管理器负责自动安排子控件的位置和大小,以便它们能够自适应父容器的大小变化或者其他因素(如窗口尺寸、文本大小等)。
- 布局管理器可以是水平布局(QHBoxLayout)、垂直布局(QVBoxLayout)、网格布局(QGridLayout)等。
- 布局相关
-
QBoxLayout的addStretch 和 setStretch
QBoxLayout 是一个抽象基类,用于实现水平布局 (QHBoxLayout) 和垂直布局 (QVBoxLayout)。- addStretch
addStretch是用来在布局中添加一个可伸缩的空白空间。这个空间会占据布局中剩余的空间,使得布局中的其他部件能够根据布局的规则进行分配。
//在水平布局(QHBoxLayout)中使用addStretch会在布局中增加一个垂直伸展的空间,从而将其他部件推向布局的两端。 QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(widget1); layout->addStretch(); // 添加伸缩空间 layout->addWidget(widget2);
- setStretch
setStretch是用来设置布局中的伸缩因子(stretch factor),控制部件在布局中的大小分配。
、、widget1和widget3将占据相等的空间,而widget2将占据两倍于其它两个部件的空间,因为它们的伸缩因子分别为1和2。 QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(widget1); layout->addWidget(widget2); layout->addWidget(widget3); layout->setStretch(0, 1); // 设置第一个部件的伸缩因子为1 layout->setStretch(1, 2); // 设置第二个部件的伸缩因子为2 layout->setStretch(2, 1); // 设置第三个部件的伸缩因子为1
- addStretch
三、应用
3.1、widget容器添加控件并布局
- 步骤
- 创建自定义QWidget类: 首先,创建一个继承自QWidget的新类。这个类将充当你自定义的widget,你可以在其中定义自己的布局和其他控件。
- 添加布局管理器: 在自定义QWidget的构造函数中,创建并设置布局管理器。将布局管理器添加到QWidget中。
- 添加控件到布局中: 将你希望显示在自定义QWidget中的控件,例如按钮、文本框等,添加到布局管理器中。
- 代码示例
//创建qwidget容器
QWidget window;
window.setWindowTitle("Layout Example");
// 创建按钮和布局管理器
QPushButton *button1 = new QPushButton("Button 1");
QPushButton *button2 = new QPushButton("Button 2");
QPushButton *button3 = new QPushButton("Button 3");
// 创建一个垂直布局管理器,并添加按钮
QVBoxLayout *vLayout = new QVBoxLayout(&window);
// 添加控件到布局
vLayout->addWidget(button1);
vLayout->addWidget(button2);
// 创建一个水平布局管理器,并添加按钮
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(button3);
// 将水平布局添加到垂直布局中
vLayout->addLayout(hLayout);
// 设置主窗口的布局
window.setLayout(vLayout);
3.2、自适应布局示例
- 基本示例
设定了布局管理器便可以使控件随布局大小改变而变化
QVBoxLayout *layout = new QVBoxLayout;
QWidget *widget = new QWidget;
QPushButton *button1 = new QPushButton("Button 1");
QPushButton *button2 = new QPushButton("Button 2");
layout->addWidget(button1);
layout->addWidget(button2);
widget->setLayout(layout);
注意事项
- 布局管理器的选择:选择合适的布局管理器是实现自适应布局的关键。根据需要,可以使用水平布局、垂直布局或网格布局来管理窗口内部的控件。
- 控件属性设置:有时需要设置控件的大小策略(size policy)或最小/最大大小,以确保它们在布局过程中按照期望的方式调整大小。
// 创建按钮
QPushButton *button1 = new QPushButton("Button 1", this);
QPushButton *button2 = new QPushButton("Button 2", this);
QPushButton *button3 = new QPushButton("Button 3", this);
// 设置按钮的大小策略
button1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
button2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
button3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// 创建水平布局并添加按钮
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->addWidget(button1);
hLayout->addWidget(button2);
hLayout->addWidget(button3);
// 创建垂直布局
QVBoxLayout *vLayout = new QVBoxLayout(this);
vLayout->addLayout(hLayout);
// 设置主布局
setLayout(vLayout);
3.3、 垂直布局2:1分割布局
3.3.1、方法1——控件大小策略
// 创建主窗口和主布局
QWidget window;
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建两个子控件,例如QWidgets或其他需要放入布局中的控件
QWidget *widget1 = new QWidget(&window);
QWidget *widget2 = new QWidget(&window);
// 设置第一个控件的大小策略,占据两倍空间
QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Expanding);
sizePolicy1.setVerticalStretch(2); // 垂直方向上拉伸因子设置为2,占据两倍空间
widget1->setSizePolicy(sizePolicy1);
// 设置第二个控件的大小策略,占据一倍空间
QSizePolicy sizePolicy2(QSizePolicy::Preferred, QSizePolicy::Expanding);
sizePolicy2.setVerticalStretch(1); // 垂直方向上拉伸因子设置为1,占据一倍空间
widget2->setSizePolicy(sizePolicy2);
// 添加子控件到布局中
layout->addWidget(widget1);
layout->addWidget(widget2);
// 设置主窗口的布局
window.setLayout(layout);
3.3.2、方法2——布局setStretch方法
QWidget window;
window.setWindowTitle("2:1 Vertical Layout Example");
// 创建一个垂直布局
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建两个Widget作为部件
QWidget *widget1 = new QWidget();
widget1->setStyleSheet("background-color: red;"); // 设置背景颜色以便区分
QWidget *widget2 = new QWidget();
widget2->setStyleSheet("background-color: green;"); // 设置背景颜色以便区分
// 将Widget添加到布局中
layout->addWidget(widget1);
layout->addWidget(widget2);
// 设置伸缩因子,实现2比1的布局
layout->setStretch(0, 2); // 第一个部件的伸缩因子为2
layout->setStretch(1, 1); // 第二个部件的伸缩因子为1
3.3.3、方法3—— 布局addWidget方法
QVBoxLayout *vbox = new QVBoxLayout(this);
// 创建两个子控件(QWidget)
QWidget *widget1 = new QWidget(this);
QWidget *widget2 = new QWidget(this);
// 设置背景颜色以便区分各个子控件
widget1->setStyleSheet("background-color: lightblue;");
widget2->setStyleSheet("background-color: lightgreen;");
// 将子控件添加到垂直布局中,并设置 stretch 因子
vbox->addWidget(widget1, 2); // stretch factor 2
vbox->addWidget(widget2, 1); // stretch factor 1
// 设置布局管理器
setLayout(vbox);
3.3.4、方法4——QSplitter与布局结合
QSplitter
- 定义
- QSplitter 是一个控件,用于在用户界面中创建可调整大小的分割窗格。它允许用户通过拖动分隔条来调整包含的子部件的大小。
- QSplitter 不是布局管理器,而是一种容器,可以嵌套在布局管理器中使用,用于管理其中的子部件的大小和位置。
- 通过 addWidget方法,可以向 QSplitter 中添加子部件,并通过 setSizes 方法来手动设置每个子部件的大小。
- 与QBoxLayout关系
- 使用场景:通常情况下,你会在用户界面中使用 QBoxLayout 来安排和管理控件的布局。如果希望在布局中创建可调整大小的分割窗格,可以将 QSplitter 嵌套在 QBoxLayout 中的一个或多个部件中。
- 嵌套关系:例如,可以创建一个垂直布局 (QVBoxLayout),在其中添加一个 QSplitter,然后向 QSplitter 中添加子部件。这样可以在垂直布局中创建多个可调整大小的区域。
- 协同使用:在实际的界面设计中,QSplitter 和 QBoxLayout 可以协同工作,以实现复杂的布局需求。例如,一个水平布局中可能包含一个垂直的 QSplitter,在其中又包含多个水平或垂直布局。
// 创建主窗口
QWidget mainWindow;
mainWindow.setWindowTitle("QSplitter with Layout Example");
mainWindow.resize(600, 400);
// 创建垂直布局管理器
QVBoxLayout *mainLayout = new QVBoxLayout(&mainWindow);
// 创建 QSplitter
QSplitter *splitter = new QSplitter(Qt::Vertical);
// 创建两个文本编辑器作为 QSplitter 的子部件
QTextEdit *textEdit1 = new QTextEdit;
QTextEdit *textEdit2 = new QTextEdit;
// 将子部件添加到 QSplitter 中
splitter->addWidget(textEdit1);
splitter->addWidget(textEdit2);
// 设置子部件的初始大小比例,2:1
splitter->setSizes(QList<int>() << 2 << 1);
// 将 QSplitter 添加到主布局中
mainLayout->addWidget(splitter);
// 设置主窗口的布局
mainWindow.setLayout(mainLayout);
// 显示主窗口
mainWindow.show();