Qt第三课 ----------布局
作者前言
🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂
布局
- **作者前言**
- 介绍
- 垂直布局
- 水平布局
- 网格布局
- 表单布局
- Spacer
- SpacerItem添加逻辑
介绍
前面我们写过很多的Qt代码, 我们可以通过代码去布局,
也就是每个控件所在的位置, 都需要计算坐标, 最终通过 setGeometry 或者 move ⽅式摆放过去.这种设定⽅式其实并不⽅便. 尤其是界⾯如果内容⽐较多, 不好计算. ⽽且⼀个窗⼝⼤⼩往往是可以调整的, 按照绝对定位的⽅式, 也⽆法⾃适应窗⼝⼤⼩.
还有就是通过ui文件手动布局,但是这种布局不太好,因为无法明确的分布好位置, 窗口的大小也很难控制,
所以就有以下布局
垂直布局
使⽤ QVBoxLayout 表⽰垂直的布局管理器 layout表示布局
属性如下:
这个只是一个布局管理器,所以没有信号函数
我们简单的写一个代码
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QVBoxLayout * verticallayout = new QVBoxLayout(this);//这里指定垂直管理器放到this中, 如果设置没有,后面就需要添加
//创建三个按钮
QPushButton * buttonOne = CreateButton(verticallayout);
QPushButton * buttonTwo = CreateButton(verticallayout);
QPushButton * buttonTherr = CreateButton(verticallayout);
//this->setLayout(verticallayout);//如果布局创建没有指定对象树,需要使用
}
Widget::~Widget()
{
delete ui;
}
QPushButton * Widget::CreateButton( QVBoxLayout * verticallayout)
{
QPushButton * button = new QPushButton("按");//这里不设置this因为我们要把按钮放到QVBoxLayout里
verticallayout->addWidget(button);
return button;
}
创建一个有三个按钮的垂直布局, 然后添加到this中
效果如下:
这个布局可以随着窗口的变化而变化,
需要注意的是: 一个widget窗口只能设置一个布局,
如下情况, 如果碰见一个widget窗口设置多个布局,可能里面是创建多个widget,每个widget添加一个布局,如图:
在Qt的ui文件里面设置这样,虽然我们看见的是一个widget添加了两个布局,其实不是,而是在在里面先创建了两个widget窗口,然后每个窗口添加一个布局,当我们运行出来进行拉伸窗口,就会发现, 里面的布局不会随窗口的变化而变化, 我们可以去查看对于的代码
如图:
可以看见里面嵌套了两个widget
水平布局
使⽤ QHBoxLayout 表⽰垂直的布局管理器. H 是 horizontal 的缩写.
水平管理器的属性和垂直管理器的是一样的
下面我们写一个简单的代码来演示一下
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// CreateLayout(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::CreateLayout(QWidget * parent)
{
//布局创建
QHBoxLayout * horizontallayout = new QHBoxLayout();
//布局添加控件
horizontallayout->addWidget(new QPushButton("按钮"));
horizontallayout->addWidget(new QPushButton("按钮"));
horizontallayout->addWidget(new QPushButton("按钮"));
horizontallayout->addWidget(new QPushButton("按钮"));
parent->setLayout(horizontallayout);
horizontallayout->addLayout(CreateVLayout());//水平布局里面嵌套垂直布局
}
QVBoxLayout * Widget::CreateVLayout()
{
//布局创建
QVBoxLayout * vLayout = new QVBoxLayout();
//布局添加控件
vLayout->addWidget(new QPushButton("按钮"));
vLayout->addWidget(new QPushButton("按钮"));
vLayout->addWidget(new QPushButton("按钮"));
vLayout->addWidget(new QPushButton("按钮"));
return vLayout;
}
void Widget::on_pushButton_clicked()
{
//添加
QString name("窗口");
ui->tabWidget->addTab(new QWidget(),name+QString::number(ui->tabWidget->currentIndex()));
}
void Widget::on_pushButton_2_clicked()
{
//删除当前的窗口
if(ui->tabWidget->currentIndex() >=0)
ui->tabWidget->removeTab(ui->tabWidget->currentIndex());
}
void Widget::on_pushButton_3_clicked()
{
CreateLayout(ui->tabWidget->currentWidget());
ui->tabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}
效果:
注意:布局里面可以嵌套布局,Layout ⾥⾯可以再嵌套上其他的 layout, 从⽽达到更复杂的布局效果.
网格布局
Qt 中提供了 QGridLayout ⽤来实现⽹格布局的效果. 可以达到 M * N 的这种⽹格的效果
属性如下:
下面我们写一个简单的:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
CreateGridlayout(this);
}
Widget::~Widget()
{
delete ui;
}
QGridLayout *Widget::CreateGridlayout(QWidget * parent)
{
//创建一个表格布局
QGridLayout* grid = new QGridLayout();
//创建三个按钮
QPushButton *buttonOne = new QPushButton("按钮");
QPushButton *buttonTwo = new QPushButton("按钮");
QPushButton *buttonThree = new QPushButton("按钮");
grid->addWidget(buttonOne, 0,0);
grid->addWidget(buttonTwo, 0,1);
grid->addWidget(buttonThree, 5,100);//不会间隔很远
parent->setLayout(grid);
return grid;
}
效果图:
在代码中, 设置了 grid->addWidget(buttonThree, 5,100),这个代码, 虽然写了很大,但是实际运行出来间隔是不大的因为,每一个按钮都会占据一行或者一列,但是这个值和上⼀个值之间并
没有其他的元素,不会因为设置很大就间隔很多,
除此之外,我们会发现,不管是啥布局,创建出来的控件的大小和间隔都是一样的,如果我们想创建一些大小和间隔不同的控件, 就需要我们去调节拉伸系数(比例)
在此代码的基础上我们添加列拉伸系数看看
grid->setColumnStretch(0,0);
grid->setColumnStretch(1,9);//第二列的大小是第一列大小的9倍
效果如下:
如果倍数为0的话,就是不参与拉伸,大小是固定的了
如果使用行的拉伸系数的话,直接使用会看不见效果的 直接设置 setRowStretch 效果不明显, 因为每个按钮的⾼度是固定的. 需要把按钮的垂直⽅向的 sizePolicy 属性设置为 QSizePolicy::Expanding 尽可能填充满布局管理器, 才能看到效果,
sizepolicy的其中的一个枚举类型,如图:
使⽤ setSizePolicy 设置按钮的尺⼨策略. 可选的值如下:
• QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响。
• QSizePolicy::Minimum : 控件的最⼩尺⼨为固定值,布局时不会超过该值。
• QSizePolicy::Maximum : 控件的最⼤尺⼨为固定值,布局时不会⼩于该值。
• QSizePolicy::Preferred : 控件的理想尺⼨为固定值,布局时会尽量接近该值。
• QSizePolicy::Expanding : 控件的尺⼨可以根据空间调整,尽可能占据更多空间。
• QSizePolicy::Shrinking : 控件的尺⼨可以根据空间调整,尽可能缩⼩以适应空间。
我们重新写一个新的代码进一步演示
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QGridLayout * grid = CreateGridlayout(this);
grid->setColumnStretch(0,1);//如果不设置,就会固定大小
grid->setColumnStretch(1,9);//第二列的大小是第一列大小的9倍
grid->setRowStretch(0,1);//如果不设置,就会固定大小
grid->setRowStretch(1,2);//第二行的大小是第一行大小的2倍
}
Widget::~Widget()
{
delete ui;
}
QGridLayout *Widget::CreateGridlayout(QWidget * parent)
{
//创建一个表格布局
QGridLayout* grid = new QGridLayout();
//创建三个按钮
QPushButton *buttonOne = CreateButton();
QPushButton *buttonTwo =CreateButton();
QPushButton *buttonThree = CreateButton();
grid->addWidget(buttonOne, 0,0);
grid->addWidget(buttonTwo, 0,1);
grid->addWidget(buttonThree, 1,0);//不会间隔很远
parent->setLayout(grid);
return grid;
}
QPushButton *Widget::CreateButton()
{
QPushButton *button = new QPushButton("按钮");
//给按钮设置在水平和垂直的方向尽可能的伸展
button->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
return button;
}
效果图:
表单布局
使⽤ QFormLayout 创建表单,属于是 QGridLayout 的特殊情况, 专⻔⽤于实现两列表单的布局
这种表单布局多⽤于让⽤⼾填写信息的场景. 左侧列为提⽰, 右侧列为输⼊框
属性如下:
addRow(): 添加一行,通常包含一个标签和一个控件。
*addRow(QString, QWidget)**: 添加一行,使用字符串作为标签。
setLabelAlignment(): 设置标签的对齐方式。
setSpacing(): 设置控件之间的间距。
setMargin(): 设置布局的边缘间距。
写一个简单的代码:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setLayout(CreateForm());
}
Widget::~Widget()
{
delete ui;
}
QFormLayout *Widget::CreateForm()
{
//创建表单
QFormLayout* form = new QFormLayout();
//创建三个标签和输入框
CreateLabel_InputBox_And_Add(form, "账号:","请输入账号");
CreateLabel_InputBox_And_Add(form, "密码:","请输入密码");
CreateLabel_InputBox_And_Add(form, "邀请码:","请输入邀请码");
// 提交按钮
QPushButton * button = new QPushButton("提交");
form->addRow(button);
form->setMargin(300);//边框距离
form->setSpacing(50);
form->setHorizontalSpacing(10);,水平方向的控件之间的间距
return form;
}
void Widget::CreateLabel_InputBox_And_Add(QFormLayout *form, QString name,QString textValue)
{
//创建标签
QLabel * label = new QLabel(name);
//创建输入框
QLineEdit * lineEdit1 = new QLineEdit();
lineEdit1->setPlaceholderText(textValue);
form->addRow(label, lineEdit1);
}
效果如下:
Spacer
使⽤布局管理器的时候, 可能需要在控件之间, 添加⼀段空⽩. 就可以使⽤ QSpacerItem 来表⽰.
这个在布局中添加这个,不太一样,下面我们演示一下:
属性如下:
代码如下:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
CreateLayot<QHBoxLayout>(this);
}
Widget::~Widget()
{
delete ui;
}
template<typename v = QLayout>
v * Widget::CreateLayot(QWidget * parent)
{
//创建布局
v* layout = new v();
//创建一个间隙
QSpacerItem * spacer= new QSpacerItem(200,100);
if(typeid (v).name() != typeid (QGridLayout).name())
{
//这里的空白的间隙添加的位置是看添加的逻辑
layout->addWidget(new QPushButton("按钮"));
layout->addSpacerItem(spacer);
layout->addWidget(new QPushButton("按钮"));
}
parent->setLayout(layout);
}
效果图:
SpacerItem添加逻辑
如果我们要把QSpacerItem添加到第一个按钮前面, 我们需要把代码添加到前面就行,
如图: