Qt的简单布局管理说明

news/2024/10/28 10:17:27/

目录

Qt的几个Layout

QBoxLayout

一个例子:

一些常见的API

QGridLayout

一个例子:

API

QFormLayout

例子

API

QStackedLayout

一些例子

API

其他

QSplitter

一些例子

API

附注


这里不是具体的好看的界面设计教程,但是打算说一下:优先使用布局管理,可以事半功倍的拜托对size的管理。

Qt的几个Layout

Qt主要有这些Layout类:

  • QVBoxLayout:表达的是按照垂直方向分配控件,一眼看过去控件按照垂直排列

  • QHBoxLayout:表达的是按照水平方向分配控件,一眼看过去控件按照水平排列

  • QGridLayout:网格布局,对于那些想要按照整整齐齐的网状布局,这个玩意最好

  • QFormLayout:设计表单的时候使用,可以更加美观!

  • QStackedLayout:堆叠布局,也就是对于那些希望在同一个Widget中一次只显示一个internal component的情况下,使用这个是最合适的

QBoxLayout

当然下分了QHBoxLayout和QVBoxLayout的,但是这不要紧,只是水平还是垂直的区分。笔者最近常用的是QHBoxLayout,就选择这个作为样板吧。

我上面说了,这个就是水平排布。默认的时候是居中对齐,当然可以修改Alignment设置更多的对齐方式(笔者建议一开始的所有的状态都在Designer中设置比较好)

我们在Designer中设置完一个Widget的Layout之后,就可以直接拖控件到这个Widget帮助我们自动布局了。那代码端呢?答案是使用addWidget这个函数,

addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = 0)

当然还可以添加spacing,注意会在末尾添加,所以想要在控件之间添加spacing需要:

addWidget(...)
addSpacing(...)
addWidget(...)

或者有的时候想要从布局中找Widget,那可以使用itemAt来索引。

一个例子:

#include "Widget.h"
#include <QLabel>
#include <QPushButton>
#include "ui_Widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {// ui->setupUi(this);QVBoxLayout *vLayout = new QVBoxLayout(this);QHBoxLayout *hLayout = new QHBoxLayout(this);
​hLayout->addWidget(new QPushButton("Button A"));hLayout->addWidget(new QPushButton("Button B"));
​vLayout->addLayout(hLayout);  // 嵌套水平布局vLayout->addWidget(new QLabel("Label Below Buttons"));
​setLayout(vLayout);
}
​
Widget::~Widget() {delete ui;
}
一些常见的API
方法名称参数描述
addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = 0)组件指针,伸缩因子(默认为0),对齐方式(默认为0)将一个子组件添加到布局中,支持伸缩和对齐设置。
addLayout(QLayout *layout, int stretch = 0)布局指针,伸缩因子(默认为0)将另一个布局添加到当前布局中,支持伸缩设置。
addSpacing(int size)空间大小布局中添加一个固定大小的空白区域。
addStretch(int stretch = 0)伸缩因子(默认为0)布局中添加一个可伸缩的空白区域。
setSpacing(int spacing)间距大小设置布局中子组件之间的间距。
setContentsMargins(int left, int top, int right, int bottom)四个边缘的外边距设置布局的外边距,控制布局与窗口边界之间的距离。
setAlignment(QWidget *widget, Qt::Alignment alignment)组件指针,对齐方式设置指定组件的对齐方式。
insertWidget(int index, QWidget *widget, int stretch = 0, Qt::Alignment alignment = 0)索引,组件指针,伸缩因子(默认为0),对齐方式(默认为0)在指定索引位置插入一个组件,并设置伸缩和对齐。
insertLayout(int index, QLayout *layout, int stretch = 0)索引,布局指针,伸缩因子(默认为0)在指定索引位置插入一个布局
removeWidget(QWidget *widget)组件指针布局中移除指定的组件。
takeAt(int index)索引移除并返回指定索引处的布局项。
count()返回布局中子组件的数量。
itemAt(int index)索引返回指定索引处的布局项。
geometry()返回布局的几何矩形,表示布局的边界。
invalidate()使布局无效,强制重新计算子组件的位置和大小。
sizeHint()返回布局的推荐大小。
minimumSize()返回布局的最小大小。
maximumSize()返回布局的最大大小。
setEnabled(bool)是否启用设置布局的启用状态。
setParent(QWidget *parent)父组件指针设置布局的父组件。

QGridLayout

网格分布!现在我们的控件可以看起来更加好看了一些,

这样的分布就是一个典型的表格分布。我们完全可以搓一个出来的(笔者建议你试试)

GPT说:他的特点是:

  • 网格排列:子组件可以在一个由行和列构成的网格中自由放置。

  • 灵活性:支持跨行和跨列放置组件,允许组件占据多个单元格。

  • 自动调整布局会自动调整组件的大小,确保它们在窗口大小变化时仍然保持合理的显示。

你可以自己动手试试。

一个例子:
#include "Widget.h"
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include "ui_Widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {// ui->setupUi(this);// 创建布局QGridLayout *layout = new QGridLayout(this);
​// 创建显示屏QLineEdit *display = new QLineEdit();display->setReadOnly(true);layout->addWidget(display, 0, 0, 1, 4);  // 占据第0行的4列
​// 创建按钮QStringList buttonLabels = {"7", "8", "9", "/", "4", "5", "6", "*","1", "2", "3", "-", "0", "C", "=", "+"};
​int row = 1;int col = 0;
​for (const QString &label : buttonLabels) {QPushButton *button = new QPushButton(label);button->setMinimumSize(QSize(50, 35));layout->addWidget(button, row, col);col++;if (col > 3) {  // 每4个按钮换行col = 0;row++;}}
​// 设置布局setLayout(layout);
}
​
Widget::~Widget() {delete ui;
}

API
方法名称参数描述
addWidget(QWidget *widget, int row, int column, int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0)组件指针,行号,列号,行跨度(默认为1),列跨度(默认为1),对齐方式(默认为0)将一个子组件添加到指定的网格位置,支持跨行和跨列的设置。
setSpacing(int spacing)间距大小设置网格中子组件之间的间距。
setContentsMargins(int left, int top, int right, int bottom)四个边缘的外边距设置布局的外边距,控制布局与窗口边界之间的距离。
setRowStretch(int row, int stretch)行号,伸缩因子设置指定行的伸缩因子。
setColumnStretch(int column, int stretch)列号,伸缩因子设置指定列的伸缩因子。
removeWidget(QWidget *widget)组件指针布局中移除指定的组件。
itemAt(int index)索引返回指定索引处的布局项。
count()返回布局中子组件的数量。
takeAt(int index)索引移除并返回指定索引处的布局项。
geometry()返回布局的几何矩形,表示布局的边界。
invalidate()使布局无效,强制重新计算子组件的位置和大小。
sizeHint()返回布局的推荐大小。
minimumSize()返回布局的最小大小。
maximumSize()返回布局的最大大小。
setEnabled(bool)是否启用设置布局的启用状态。
addItem(QLayoutItem *item, int row, int column, int rowSpan = 1, int columnSpan = 1)布局项,行号,列号,行跨度(默认为1),列跨度(默认为1)将一个布局项添加到网格中。
addLayout(QLayout *layout, int row, int column, int rowSpan = 1, int columnSpan = 1)布局指针,行号,列号,行跨度(默认为1),列跨度(默认为1)将另一个布局添加到指定位置。

QFormLayout

比起来,他比更加通用的QGridLayout更加的特化了:

  • 标签和控件对齐:标签和控件以行的形式排列,标签通常位于控件的左侧或上方,方便用户阅读和输入。

  • 自适应:控件和标签的大小会自动调整,以适应布局和窗口大小的变化。

  • 易于使用:提供简单的方法添加标签和控件,快速构建表单界面。

例子
#include "Widget.h"
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include "ui_Widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {QFormLayout *formLayout = new QFormLayout(this);
​// 创建控件QLineEdit *nameEdit  = new QLineEdit();QLineEdit *emailEdit = new QLineEdit();QLineEdit *phoneEdit = new QLineEdit();
​// 添加标签和控件到布局formLayout->addRow("Name:", nameEdit);formLayout->addRow("Email:", emailEdit);formLayout->addRow("Phone:", phoneEdit);
​// 添加提交按钮QPushButton *submitButton = new QPushButton("Submit");formLayout->addRow(submitButton);
​setLayout(formLayout);
}
​
Widget::~Widget() {delete ui;
}
API
方法名称参数描述
addRow(const QString &labelText, QWidget *field)标签文本,控件指针添加一行,包含标签和对应的控件。
addRow(QWidget *label, QWidget *field)标签控件,控件指针添加一行,使用指定的标签控件和对应的控件。
addRow(QWidget *label, QWidget *field, int rowSpan)标签控件,控件指针,行跨度添加一行,允许标签和控件占用多个行。
setLabelAlignment(Qt::Alignment alignment)对齐方式设置所有标签的对齐方式。
setFormAlignment(Qt::Alignment alignment)对齐方式设置所有控件的对齐方式。
insertRow(int row, const QString &labelText, QWidget *field)行号,标签文本,控件指针在指定行插入一行,包含标签和控件。
insertRow(int row, QWidget *label, QWidget *field)行号,标签控件,控件指针在指定行插入一行,使用指定的标签控件和对应的控件。
removeRow(int row)行号移除指定行。
itemAt(int index)索引返回指定索引处的布局项。
count()返回布局中子组件的数量。
takeAt(int index)索引移除并返回指定索引处的布局项。
setContentsMargins(int left, int top, int right, int bottom)四个边缘的外边距设置布局的外边距,控制布局与窗口边界之间的距离。
setSpacing(int spacing)间距大小设置标签和控件之间的间距。
setLabelFont(const QFont &font)字体设置所有标签的字体。
setFormAlignment(Qt::Alignment alignment)对齐方式设置所有控件的对齐方式。
setWidget(int row, int column, QWidget *widget)行号,列号,控件指针设置指定行列位置的控件。
getLabelAlignment()获取标签的对齐方式。
getFormAlignment()获取控件的对齐方式。
isEmpty()检查布局是否为空。

QStackedLayout

这个玩意就是一个Stack,保证可以在一叠Widget中选出一个进行显示。

动态切换:可以通过 setCurrentIndex()setCurrentWidget() 方法动态切换当前显示的控件。

灵活性:可以在运行时添加或移除控件,支持高度动态的用户界面设计。

用户友好:适合实现复杂的用户交互和视图切换。

一些例子
#include "Widget.h"
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QStackedLayout>
#include "ui_Widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {QStackedLayout *stackedLayout = new QStackedLayout(this);
​// 创建个人信息页面QWidget     *personalInfoPage = new QWidget();QVBoxLayout *personalLayout   = new QVBoxLayout(personalInfoPage);personalLayout->addWidget(new QLabel("Personal Information"));personalLayout->addWidget(new QLabel("Name:"));QLineEdit *nameEdit = new QLineEdit();personalLayout->addWidget(nameEdit);personalLayout->addWidget(new QLabel("Email:"));QLineEdit *emailEdit = new QLineEdit();personalLayout->addWidget(emailEdit);
​QPushButton *nextToAddressButton = new QPushButton("Next");personalLayout->addWidget(nextToAddressButton);stackedLayout->addWidget(personalInfoPage);
​// 创建地址信息页面QWidget     *addressInfoPage = new QWidget();QVBoxLayout *addressLayout   = new QVBoxLayout(addressInfoPage);addressLayout->addWidget(new QLabel("Address Information"));addressLayout->addWidget(new QLabel("Street:"));QLineEdit *streetEdit = new QLineEdit();addressLayout->addWidget(streetEdit);addressLayout->addWidget(new QLabel("City:"));QLineEdit *cityEdit = new QLineEdit();addressLayout->addWidget(cityEdit);
​QPushButton *backToPersonalButton = new QPushButton("Back");QPushButton *nextToConfirmButton  = new QPushButton("Next");addressLayout->addWidget(backToPersonalButton);addressLayout->addWidget(nextToConfirmButton);stackedLayout->addWidget(addressInfoPage);
​// 创建确认信息页面QWidget     *confirmationPage   = new QWidget();QVBoxLayout *confirmationLayout = new QVBoxLayout(confirmationPage);confirmationLayout->addWidget(new QLabel("Confirmation Information"));confirmationLayout->addWidget(new QLabel("Please review your information."));
​QPushButton *backToAddressButton = new QPushButton("Back");QPushButton *submitButton        = new QPushButton("Submit");confirmationLayout->addWidget(backToAddressButton);confirmationLayout->addWidget(submitButton);stackedLayout->addWidget(confirmationPage);
​// 设置信号与槽connect(nextToAddressButton, &QPushButton::clicked, [=]() {stackedLayout->setCurrentIndex(1);  // 切换到地址信息页面});connect(backToPersonalButton, &QPushButton::clicked, [=]() {stackedLayout->setCurrentIndex(0);  // 切换回个人信息页面});connect(nextToConfirmButton, &QPushButton::clicked, [=]() {stackedLayout->setCurrentIndex(2);  // 切换到确认信息页面});connect(backToAddressButton, &QPushButton::clicked, [=]() {stackedLayout->setCurrentIndex(1);  // 切换回地址信息页面});connect(submitButton, &QPushButton::clicked, this,&Widget::submitForm);  // 提交表单,这个API可以自己定义!
​setLayout(stackedLayout);resize(400, 300);
}
Widget::~Widget() {delete ui;
}

API
方法名称参数描述
addWidget(QWidget *widget)组件指针将一个组件添加到堆叠布局中。
insertWidget(int index, QWidget *widget)索引,组件指针在指定位置插入一个组件。
setCurrentIndex(int index)索引设置当前显示的组件索引。
setCurrentWidget(QWidget *widget)组件指针设置当前显示的组件。
currentIndex()返回当前显示组件的索引。
currentWidget()返回当前显示的组件。
removeWidget(QWidget *widget)组件指针布局中移除指定的组件。
count()返回布局中子组件的数量。
itemAt(int index)索引返回指定索引处的布局项。
takeAt(int index)索引移除并返回指定索引处的布局项。
setContentsMargins(int left, int top, int right, int bottom)四个边缘的外边距设置布局的外边距。
setSpacing(int spacing)间距大小设置组件之间的间距。
clear()清空布局,移除所有组件。
setEnabled(bool)是否启用设置布局的启用状态。
widget(int index)索引返回指定索引处的组件指针。
addLayout(QLayout *layout)布局指针添加一个子布局
isEmpty()检查布局是否为空。
minimumSize()返回布局的最小大小。
maximumSize()返回布局的最大大小。

其他

QSplitter

这个很酷:实现的就是用户拖拽一个竖线条实现对各个控件的重新分配。

一些例子
#include "Widget.h"
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSplitter>
#include <QTextEdit>
#include "ui_Widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
​// 创建文本框1QTextEdit *textEdit1 = new QTextEdit();textEdit1->setPlaceholderText("Text Editor 1");splitter->addWidget(textEdit1);
​// 创建文本框2QTextEdit *textEdit2 = new QTextEdit();textEdit2->setPlaceholderText("Text Editor 2");splitter->addWidget(textEdit2);
​// 创建按钮QPushButton *button = new QPushButton("Submit");button->setFixedWidth(100);splitter->addWidget(button);
​// 设置布局QVBoxLayout *layout = new QVBoxLayout(this);layout->addWidget(splitter);setLayout(layout);
}
Widget::~Widget() {delete ui;
}

API
方法名称参数描述
addWidget(QWidget *widget)组件指针向分隔器添加一个子组件。
insertWidget(int index, QWidget *widget)索引,组件指针在指定位置插入一个子组件。
setOrientation(Qt::Orientation orientation)方向(水平或垂直)设置分隔器的方向。
setStretchFactor(int index, int stretch)索引,拉伸因子设置指定索引的子组件的拉伸因子,用于调整其相对大小。
setSizes(const QList<int> &sizes)大小列表设置所有子组件的大小。
sizes()返回所有子组件的当前大小列表。
handle(int index)索引返回指定索引的分隔条控件。
setCollapsible(int index, bool collapse)索引,是否可折叠设置指定索引的子组件是否可折叠。
isCollapsible(int index)索引检查指定索引的子组件是否可折叠。
setOpaqueResize(bool opaque)是否透明调整设置在调整大小时是否透明。
setChildrenCollapsible(bool collapse)是否可折叠设置所有子组件是否可折叠。
childrenCollapsible()检查所有子组件是否可折叠。
setHandleWidth(int width)宽度设置分隔条的宽度。
handleWidth()返回分隔条的宽度。
setFrameShape(QFrame::Shape shape)形状设置分隔器的框架形状。
frameShape()返回分隔器的框架形状。

附注

附注:一些Layout可以修改伸缩因数来达到调整空间大小比例的特性,下面就是一个例子:

我们的Widget内部使用了QHLayout后,设置伸缩因数依次为0,0,0;0,0,1;1,1,2!他们依次表达为:

  • 全等表达平均分配,伸缩的时候几个按钮会按照均匀分配的方式均匀变化

  • 存在0的:表达该index指示下的控件不会发生伸缩,恒定大小

  • 比例变化:比如说1:1:2表达的是变化是按照1:1:2分配的,其中初始状态的大小也是按照1:1:2分配的。


http://www.ppmy.cn/news/1542569.html

相关文章

DDei 在线设计器 V1.2.41 版发布

​ DDei 在线设计器 V1.2.41 版本带来了新功能、提升了性能、增强了稳定性、扩展了多个回调函数。 提供了简版布局与之配套的简版控件工具箱和顶部菜单&#xff0c;并支持通过 vue 来扩展菜单。 2.由canvas渲染改为canvshtml混合渲染&#xff0c;提升清晰度和渲染性能&#xf…

Leetcode 3336. Find the Number of Subsequences With Equal GCD

Leetcode 3336. Find the Number of Subsequences With Equal GCD 1. 解题思路2. 代码实现 题目链接&#xff1a;3336. Find the Number of Subsequences With Equal GCD 1. 解题思路 这一题没能自力搞定&#xff0c;挺伤心的&#xff0c;看大佬的代码之后发现思路上是一个非…

使用 python中 pandas 将 Excel 转换为 CSV 文件

在数据处理和分析中&#xff0c;我们经常需要将 Excel 文件转换为 CSV 格式。CSV 文件因其简单、易于处理的特点&#xff0c;广泛用于数据交换。本文将介绍如何使用 wxPython 创建一个简单的图形用户界面&#xff08;GUI&#xff09;&#xff0c;结合 pandas 库&#xff0c;实现…

每天五分钟深度学习框架pytorch:从底层实现一元线性回归模型

本文重点 本节课程我们继续搭建一元线性回归模型,不同的是这里我们不使用pytorch框架已经封装好的一些东西,我们做这个目的是为了更加清楚的看到pytorch搭建模型的本质,为了更好的理解,当然实际中我们还是使用pytorch封装好的一些东西,不要重复造轮子。 模型搭建 #定义…

NLP自然语言处理中的Attention机制原理揭秘

NLP自然语言处理中的Attention机制原理揭秘 引言 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;Attention机制已经成为提升模型性能和效果的重要技术之一。它模仿了人类在处理信息时的注意力机制&#xff0c;使得模型能够在处理输入数据时&#xff0c;动态地聚…

语法索引不会生效

使用sql语句时,哪些语法索引不会生效 在SQL中&#xff0c;当使用某些语法时&#xff0c;索引可能不会生效。以下是一些常见情形&#xff1a; 使用函数时&#xff08;如WHERE YEAR(column) 2021&#xff09;&#xff0c;索引可能不会被使用&#xff0c;因为函数会导致索引无法…

grafana 8.0 添加钉钉告警

钉钉配置 添加机器人 找到群&#xff0c;选择自定义机器人 自定义机器人配置 Grafana 通知渠道配置 配置告警规则 出现Template variables are not supported in alert queries&#xff0c;把变量都改为常量 改为 Prometheus 微服务引入Prometheus相关包后 进入微服务…

LDR6020:为VR串流线方案注入高效能与稳定性

随着虚拟现实&#xff08;VR&#xff09;技术的不断发展&#xff0c;VR设备已经成为连接用户与沉浸式体验的重要桥梁。而VR串流线&#xff0c;作为这一技术的重要组成部分&#xff0c;更是承担着传输高质量图像、音频及数据的重任。在这个过程中&#xff0c;一款功能强大、性能…