一文详解Qt如何优雅的进行界面布局
作者:Fox!
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界面布局的资料请关注脚本之家其它相关文章!