QT 布局

简介

Qt 中的布局有三种方式,水平布局,垂直布局,栅格布局。

通过ui设置布局

我们先创建一个窗口应用程序,程序名叫layout,基类选择QMainWindow。但我们不使用这个mainwindow,我们创建一个Qt应用程序类Login,Qt会为我们自动生成login.ui文件。我们进入ui文件编辑,添加一个label,提示改为用户: , 在后边添加一个lineedit控件,按住ctrl鼠标依次点击这两个控件选中后,再点击工具栏的水平布局按钮就可以看到用户label和输入框处于同一水平线了。但是输入框会被拉长,而且label和输入框占满了整个水平空间。这时我们可以通过拖动左侧控件列表中的Horizonal Spacer,将其放入用户标签的左侧,再拖动一个Horizonal Spacer将其放在输入框的右侧,就可以看到用户标签和输入框被挤在中间了,并且两侧留有空间了。Spacer可以设置几种模式,包括fixed,expanding, maximum, minimum等模式。
依次类推,我们在添加密码标签和输入框,以及登录和注册按钮,通过ui界面的控件调整布局。
https://cdn.llfc.club/1665043183045.jpg

通过代码设置布局

上面我们通过ui设置了布局,接下来我们通过代码设置布局,设置注册界面的布局
注册类的声明如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef REGISTER_H
#define REGISTER_H

#include <QDialog>
#include <memory>
using namespace std;
class Login;
namespace Ui {
class Register;
}

class Register : public QDialog
{
Q_OBJECT

public:
explicit Register(QWidget *parent = nullptr);
~Register();
void set_login(const weak_ptr<Login> &_login);
private:
Ui::Register *ui;
weak_ptr<Login> _login;
QPushButton* _reg_btn;
public slots:
void ShowLogin();
};

#endif // REGISTER_H

因为要实现登录和注册界面之间的切换,所以Register类包含了Login类的弱指针,Register类的具体实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "register.h"
#include "ui_register.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSpacerItem>

Register::Register(QWidget *parent) :
QDialog(parent),
ui(new Ui::Register)
{
ui->setupUi(this);
this->setMaximumSize(QSize(300,350));
this->setMinimumSize(QSize(300,350));
auto vbox_layout = new QVBoxLayout();

auto verticalSpacer1 = new QSpacerItem(40,20, QSizePolicy::Minimum, QSizePolicy::Expanding);
vbox_layout->addItem(verticalSpacer1);
QSpacerItem *name_item1 = new QSpacerItem(40,20, QSizePolicy::Fixed, QSizePolicy::Minimum);
QLabel * name_label = new QLabel();
name_label->setText("邮箱:");
QLineEdit * name_edit = new QLineEdit();
auto name_layout = new QHBoxLayout();
name_layout->addItem(name_item1);
name_layout->addWidget(name_label);
name_layout->addWidget(name_edit);
QSpacerItem *name_item2 = new QSpacerItem(40,20, QSizePolicy::Fixed, QSizePolicy::Minimum);
name_layout->addItem(name_item2);
vbox_layout->addLayout(name_layout);

QLabel * pwd_label = new QLabel();
pwd_label->setText("密码:");
QLineEdit * pwd_edit = new QLineEdit();

auto verticalSpacer2 = new QSpacerItem(40,20, QSizePolicy::Maximum, QSizePolicy::Maximum);
vbox_layout->addItem(verticalSpacer2);
auto pwd_layout = new QHBoxLayout();

QSpacerItem *pwd_item2 = new QSpacerItem(40,20, QSizePolicy::Fixed, QSizePolicy::Minimum);
QSpacerItem *pwd_item1 = new QSpacerItem(40,20, QSizePolicy::Fixed, QSizePolicy::Minimum);
pwd_layout->addItem(pwd_item1);
pwd_layout->addWidget(pwd_label);
pwd_layout->addWidget(pwd_edit);
pwd_layout->addItem(pwd_item2);
vbox_layout->addLayout(pwd_layout);

auto verticalSpacer3 = new QSpacerItem(40,30, QSizePolicy::Fixed, QSizePolicy::Maximum);
vbox_layout->addItem(verticalSpacer3);

QSpacerItem* reg_btn_item1 = new QSpacerItem(150,20, QSizePolicy::Fixed, QSizePolicy::Minimum);
_reg_btn = new QPushButton();
_reg_btn->setText("注册");
auto regbtn_layout = new QHBoxLayout();
regbtn_layout->addItem(reg_btn_item1);
regbtn_layout->addWidget(_reg_btn,5);
QSpacerItem* reg_btn_item2 = new QSpacerItem(40,20, QSizePolicy::Fixed, QSizePolicy::Minimum);

regbtn_layout->addItem(reg_btn_item2);
vbox_layout->addLayout(regbtn_layout);

auto verticalSpacer4 = new QSpacerItem(40,20, QSizePolicy::Fixed, QSizePolicy::Expanding);
vbox_layout->addItem(verticalSpacer4);
this->setLayout(vbox_layout);
}

Register::~Register()
{
delete ui;
}

void Register::set_login(const weak_ptr<Login> &login){
_login = login;
}

void Register::ShowLogin()
{

}

Register的构造函数中用代码的方式创建了一个垂直布局,垂直布局中增加了两个spacer,分别是verticalSpacer1和verticalSpacer4,以及三个水平布局pwd_layout,name_layout以及regbtn_layout,然后分别用代码的方式在三个布局中添加spacer和控件。
Login类的声明如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef LOGIN_H
#define LOGIN_H

#include <QDialog>
#include <memory>
class Register;
using namespace std;
namespace Ui {
class Login;
}

class Login : public QDialog, public std::enable_shared_from_this<Login>
{
Q_OBJECT

public:
explicit Login(QWidget *parent = nullptr);
~Login();
void initSignals();

private slots:
void on_regBtn_clicked();

private:
Ui::Login *ui;
std::shared_ptr<Register> _register;
};

#endif // LOGIN_H

Login实现如下下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "ui_login.h"
#include <QBitmap>
#include <QPainter>
#include "register.h"

Login::Login(QWidget *parent) :
QDialog(parent),
ui(new Ui::Login)
{
ui->setupUi(this);
}

void Login::initSignals(){
_register = make_shared<Register>();
//从本类转化为共享的智能指针给register类
_register->set_login(shared_from_this());
}

Login::~Login()
{
delete ui;
}

void Login::on_regBtn_clicked()
{

this->close();
_register->show();
}

main函数的实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "login.h"
#include <QApplication>
#include <memory>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
std::shared_ptr<Login> w = make_shared<Login>();
w->initSignals();
w->show();

return a.exec();
}

点击运行按钮,程序运行起来就可以从登录界面切换到注册界面了

总结

源码链接https://gitee.com/secondtonone1/qt-learning-notes