一文详解Qt如何优雅的进行界面布局

 更新时间:2024年05月24日 10:40:54   作者:Fox!  
使⽤ Qt 在界⾯上创建的控件, 都是通过 “绝对定位” 的⽅式来设定的,这种设定⽅式其实并不⽅便,尤其是界⾯如果内容⽐较多, 不好计算,所以Qt 引⼊ 布局管理器 (Layout) 机制, 来解决上述问题,需要的朋友可以参考下

1 写在前面

之前使⽤ Qt 在界⾯上创建的控件, 都是通过 “绝对定位” 的⽅式来设定的。也就是每个控件所在的位置, 都需要计算坐标, 最终通过 setGeometry 或者 move ⽅式摆放过去。

这种设定⽅式其实并不⽅便,尤其是界⾯如果内容⽐较多, 不好计算。⽽且⼀个窗⼝⼤⼩往往是可以调整的, 按照绝对定位的⽅式, 也⽆法⾃适应窗⼝⼤⼩。因此 Qt 引⼊ 布局管理器 (Layout) 机制, 来解决上述问题。

2 垂直布局

使⽤ QVBoxLayout 表⽰垂直的布局管理器,V 是 vertical 的缩写。

核⼼属性:

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上⽅边距
layoutBottomMargin下⽅边距
layoutSpacing相邻元素之间的间距

Layout 只是⽤于界⾯布局, 并没有提供信号。

代码示例:

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

    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");

    // 创建布局管理器, 并且把按钮添加进去
    // 如果创建的时候指定⽗元素为 this, 则后⾯不需要 setLayout ⽅法
    QVBoxLayout* layout = new QVBoxLayout();
    layout->addWidget(btn1);
    layout->addWidget(btn2);
    layout->addWidget(btn3);

    // 把布局管理器设置到 widget 中
    this->setLayout(layout);
}

验证结果:

使用代码的方式时我们拖拽窗口时,按钮的位置也会随着窗口的调整而改变。

我们还可以使用图形化界面的方式来进行垂直布局:

但是注意使用图形化界面的方式时我们拖拽窗口,按钮的位置不会随着窗口的调整而改变。

3 水平布局

使⽤ QHBoxLayout 表⽰垂直的布局管理器,H 是 horizontal 的缩写。

核⼼属性 (和 QVBoxLayout 属性是⼀致的)

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上⽅边距
layoutBottomMargin下⽅边距
layoutSpacing相邻元素之间的间距

代码⽰例:

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    // 创建布局管理器
    QHBoxLayout* layout = new QHBoxLayout();
    layout->addWidget(btn1);
    layout->addWidget(btn2);
    layout->addWidget(btn3);
    // 设置 layout 到 widget 上
    this->setLayout(layout);
}

结果验证:

同理我们也可以使用图形化界面的方式来创建水平布局。这里就不再演示了。

4 网格布局

Qt 中还提供了 QGridLayout ⽤来实现⽹格布局的效果,可以达到 M * N 的这种⽹格的效果。

核⼼属性:整体和 QVBoxLayout 以及 QHBoxLayout 相似,但是设置 spacing 的时候是按照垂直⽔平两个⽅向来设置的。

属性说明
layoutLeftMargin左侧边距
layoutRightMargin右侧边距
layoutTopMargin上⽅边距
layoutBottomMargin下⽅边距
layoutHorizontalSpacing相邻元素之间⽔平⽅向的间距
layoutVerticalSpacing相邻元素之间垂直⽅向的间距
layoutRowStretch⾏⽅向的拉伸系数
layoutColumnStretch列⽅向的拉伸系数

代码⽰例:

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

    // 创建 4 个按钮
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    QPushButton* btn4 = new QPushButton("按钮4");

    // 创建⽹格布局管理器, 并且添加元素
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(btn1, 0, 0);
    layout->addWidget(btn2, 0, 2);
    layout->addWidget(btn3, 1, 1);
    layout->addWidget(btn4, 1, 3);

    // 设置 layout 到窗⼝中.
    this->setLayout(layout);
}

结果验证:

我们再来看看使用下面的代码会出现什么情况:

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

    // 创建 4 个按钮
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    QPushButton* btn4 = new QPushButton("按钮4");

    // 创建⽹格布局管理器, 并且添加元素
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(btn1, 0, 0);
    layout->addWidget(btn2, 1, 0);
    layout->addWidget(btn3, 2, 0);
    layout->addWidget(btn4, 5, 0);

    // 设置 layout 到窗⼝中.
    this->setLayout(layout);
}

结果验证:

此处也要注意, 设置⾏和列的时候, 如果设置的是⼀个很⼤的值, 但是这个值和上⼀个值之间并没有其他的元素, 那么并不会在中间腾出额外的空间。

代码⽰例: 设置 QGridLayout 中元素的⼤⼩⽐例

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

    // 创建 6 个按钮
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    QPushButton* btn4 = new QPushButton("按钮4");
    QPushButton* btn5 = new QPushButton("按钮5");
    QPushButton* btn6 = new QPushButton("按钮6");

    // 创建⽹格布局管理器, 并且添加元素
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(btn1, 0, 0);
    layout->addWidget(btn2, 0, 1);
    layout->addWidget(btn3, 0, 2);
    layout->addWidget(btn4, 1, 0);
    layout->addWidget(btn5, 1, 1);
    layout->addWidget(btn6, 1, 2);
    // 设置拉伸⽐例,设置为0的话为默认大小
    // 第 0 列拉伸⽐例设为 3;
    layout->setColumnStretch(0, 3);
    // 第 1 列拉伸⽐例设为 2,
    layout->setColumnStretch(1, 2);
    // 第 2 列拉伸⽐例设为 1
    layout->setColumnStretch(2, 1);

    // 设置 layout 到窗⼝中.
    this->setLayout(layout);
}

结果验证:

另外, QGridLayout 也提供了 setRowStretch 设置⾏之间的拉伸系数。上述案例中, 直接设置 setRowStretch 效果不明显, 因为每个按钮的⾼度是固定的,需要把按钮的垂直⽅向的 sizePolicy 属性设置为 QSizePolicy::Expanding 尽可能填充满布局管理器, 才能看到效果。

代码⽰例: 设置垂直⽅向的拉伸系数。

使⽤ 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);

    // 创建 6 个按钮
    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    QPushButton* btn4 = new QPushButton("按钮4");
    QPushButton* btn5 = new QPushButton("按钮5");
    QPushButton* btn6 = new QPushButton("按钮6");
    // 设置按钮的 sizePolicy, 此时按钮的⽔平⽅向和垂直⽅向都会尽量舒展开
    btn1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    btn2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    btn3->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    btn4->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    btn5->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    btn6->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    // 创建⽹格布局管理器, 并且添加元素
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(btn1, 0, 0);
    layout->addWidget(btn2, 0, 1);
    layout->addWidget(btn3, 1, 0);
    layout->addWidget(btn4, 1, 1);
    layout->addWidget(btn5, 2, 0);
    layout->addWidget(btn6, 2, 1);
    // 设置拉伸⽐例
    // 第 0 ⾏拉伸⽐例设为 1;
    layout->setRowStretch(0, 1);
    // 第 1 ⾏拉伸⽐例设为 0, 即为固定⼤⼩, 不参与拉伸
    layout->setRowStretch(1, 0);
    // 第 2 ⾏拉伸⽐例设为 2, 即为第 2 ⾏的宽度是第 0 ⾏的 2 倍
    layout->setRowStretch(2, 2);
    // 设置 layout 到窗⼝中.
    this->setLayout(layout);
}

结果验证:

5 表单布局

除了上述的布局管理器之外, Qt 还提供了 QFormLayout , 属于是 QGridLayout 的特殊情况, 专⻔⽤于实现两列表单的布局。这种表单布局多⽤于让⽤⼾填写信息的场景,左侧列为提⽰, 右侧列为输⼊框。

代码示例:

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

    // 创建 layout
    QFormLayout* layout = new QFormLayout();
    this->setLayout(layout);
    // 创建三个 label
    QLabel* label1 = new QLabel("姓名");
    QLabel* label2 = new QLabel("年龄");
    QLabel* label3 = new QLabel("电话");
    // 创建三个 lineEdit
    QLineEdit* lineEdit1 = new QLineEdit();
    QLineEdit* lineEdit2 = new QLineEdit();
    QLineEdit* lineEdit3 = new QLineEdit();
    // 创建⼀个提交按钮
    QPushButton* btn = new QPushButton("提交");
    // 把上述元素添加到 layout 中
    layout->addRow(label1, lineEdit1);
    layout->addRow(label2, lineEdit2);
    layout->addRow(label3, lineEdit3);
    layout->addRow(NULL, btn);

}

结果验证:

以上就是一文详解Qt如何优雅的进行界面布局的详细内容,更多关于Qt界面布局的资料请关注脚本之家其它相关文章!

相关文章

  • C++ 正则表达式的应用详解

    C++ 正则表达式的应用详解

    正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等
    2021-11-11
  • C++11新增的包装器详解

    C++11新增的包装器详解

    由于函数调用可以使用函数名、函数指针、函数对象或有名称的lambda表达式,可调用类型太丰富导致模板的效率极低。包装器用于解决效率低的问题
    2022-08-08
  • C语言实现快速排序

    C语言实现快速排序

    这篇文章主要为大家详细介绍了C语言实现快速排序算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • C语言二维数组应用之井字棋游戏

    C语言二维数组应用之井字棋游戏

    这篇文章主要为大家详细介绍了C语言二维数组应用之井字棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C/C++ 活动预处理器详解

    C/C++ 活动预处理器详解

    预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理,预处理的作用就是在代码被编译前对代码做某些替换,这篇文章主要介绍了C/C++ 活动预处理器,需要的朋友可以参考下
    2022-11-11
  • Visual Studio配置静态库详细步骤和关键配置项

    Visual Studio配置静态库详细步骤和关键配置项

    这篇文章主要介绍了Visual Studio配置静态库的详细步骤和关键配置项的相关资料,静态库是一系列预先编译好的目标文件(.o文件或.obj文件)的集合,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-12-12
  • 利用C语言实现http服务器(Linux)

    利用C语言实现http服务器(Linux)

    本文将利用C语言实现一个轻量级的http服务器,使用Reactor模式,即主线程只负责监听文件描述符上是否有事件发生,有的话立即将该事件通知工作线程,感兴趣的可以了解一下
    2022-07-07
  • 利用C语言的Cairo图形库绘制太极图实例教程

    利用C语言的Cairo图形库绘制太极图实例教程

    这几天都在研究Cairo图形库,这是一个开源跨平台的图形库,相对于OpenGL来说更容易上手使用。这篇文章是利用C语言的Cairo图形库绘制了一个太极图,对大家学习Cairo图形库具有一定的参考借鉴价值,下面来一起看看吧。
    2016-12-12
  • 利用C语言实现简单三子棋游戏

    利用C语言实现简单三子棋游戏

    这篇文章主要为大家详细介绍了利用C语言实现简单三子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • 基于Qt实现日志打印系统

    基于Qt实现日志打印系统

    这篇文章主要为大家详细介绍了如何利用Qt开发一个日志打印系统,可以实现打印日志按日期、大小保存,过期删除,窗口实时显示日志,网络传输日志远程调试,需要的可以参考下
    2023-12-12

最新评论