Qt布局系统包含一组布局管理类,当界面变化时,布局系统会自动定位和调整窗口的大小,从而确保控件始排列整齐并确保界面可用。
所有QWidget子类都可以使用布局管理类。 QWidget::setLayout()函数将布局应用于QWidget子类的界面。
使用布局的最简单方法是使用内置布局管理器:QHBoxLayout,QVBoxLayout,QGridLayout和QFormLayout。本文通过QT官方的例子Basic Layouts来熟悉这几个类如何使用,运行出来之后,界面是这样的
下面先新建一个继承自QWidget的工程,开始一步一步画出这个界面
1.添加最上面的菜单file
最上面的是一个菜单栏,菜单栏里面有一个菜单,可以分别使用QT中的类QMenuBar和QMenu来创建菜单栏和菜单,然后在菜单中添加具体的菜单项即可,菜单项可以使用类QAction来创建。而该界面整体可以采用QVBoxLayout来布局每一栏,代码如下
//头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <memory>
#include <QWidget>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QVBoxLayout>
using namespace std;
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
void creatmenubar();
virtual ~Widget();
private:
Ui::Widget *ui;
shared_ptr<QMenuBar> menubar_;
shared_ptr<QMenu> menu_;
shared_ptr<QAction> exitaction_;
shared_ptr<QVBoxLayout> mainlayout_;
};
#endif // WIDGET_H
//源文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
, menubar_(make_shared<QMenuBar>(this))//创建一个菜单栏
, menu_(make_shared<QMenu>(tr("file"), this))//创建一个名字叫file的菜单
, mainlayout_(make_shared<QVBoxLayout>(this))//创建布局
{
ui->setupUi(this);
creatmenubar();
mainlayout_->setMenuBar(menubar_.get());
setLayout(mainlayout_.get());
setWindowTitle("basic layout");
}
void Widget::creatmenubar()
{
exitaction_.reset(menu_->addAction(tr("exit")));//将exit菜单项添加到菜单file中
menubar_->addMenu(menu_.get());
}
Widget::~Widget()
{
delete ui;
}
//主函数
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
上述代码添加完之后,效果如下
2.添加水平布局和其中的button
水平布局主要是用到了QGroupBox和QHBoxLayout,将四个button添加到QHBoxLayout对象中,然后设置QGroupBox的布局为QHBoxLayout对象即可,新加代码如下
//头文件代码
#include <vector>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QPushButton>
shared_ptr<QGroupBox> horizontalbox_;
shared_ptr<QHBoxLayout> horizontallayout_;
vector<shared_ptr<QPushButton>> buttons_;
//构造函数代码
, horizontalbox_(make_shared<QGroupBox>(tr("horizontal layout")))
, horizontallayout_(make_shared<QHBoxLayout>(this))
buttons_.resize(4);
creathorizontallayout();
mainlayout_->addWidget(horizontalbox_.get());
void Widget::creathorizontallayout()
{
for (int i=0;i<buttons_.size();++i) {
buttons_[i].reset(new QPushButton(tr("button%1").arg(i + 1)));//格式化显示
horizontallayout_->addWidget(buttons_[i].get());
}
horizontalbox_->setLayout(horizontallayout_.get());
}
效果如下
3.绘制栅格布局
思路和步骤2类似,依旧是创建一个QGroupBox对象和GridLayout对象,在GridLayout对象对象中创建标题显示QLabel和方框编辑栏QLineEdit,之后在布局中添加一个文本编辑栏,最后将GridLayout设置为QGroupBox对象的布局。代码如下:
//头文件
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
void creatgridlayout();
shared_ptr<QGroupBox> gridbox_;
shared_ptr<QGridLayout> gridlayout_;
vector<shared_ptr<QLabel>> labels3_;
vector<shared_ptr<QLineEdit>> linedits3_;
shared_ptr<QTextEdit> textedit3_;
//构造函数中新加代码
, gridbox_(make_shared<QGroupBox>(tr("grid layout")))
, gridlayout_(make_shared<QGridLayout>(this))
, textedit3_(make_shared<QTextEdit>(this))
labels3_.resize(3);
linedits3_.resize(3);
creatgridlayout();
mainlayout_->addWidget(gridbox_.get());
void Widget::creatgridlayout()
{
for (int i=0;i<labels3_.size();++i) {
labels3_[i].reset(new QLabel(tr("line%1").arg(i+1)));
gridlayout_->addWidget(labels3_[i].get(), i+1, 0);//位于第一列,每行一个QLabel对象
}
for (int i=0;i<linedits3_.size();++i) {
linedits3_[i].reset(new QLineEdit);
gridlayout_->addWidget(linedits3_[i].get(), i+1, 1);//位于第二列,每行一个QLineEdit对象
}
gridlayout_->addWidget(textedit3_.get(),0, 2, 4, 1);//位于第三列,第一行,占空间四行一列(textedit3_本身占一列,外加3列,所以是4列)
gridbox_->setLayout(gridlayout_.get());
}
效果如下
QGridLayout中比较重要的一个函数就是addWidget,该函数有两种形式
void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment = Qt::Alignment())
void QGridLayout::addWidget(QWidget *widget, int fromRow, intfromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment())
第一种就是在布局中添加一个item,并指定起始行和列,第二种形式也指定了起始行和列,但是后两个参数也指定了该item会占多少行和列
4.绘制formlayout
思路依旧是创建一个QGroupBox对象和QFormLayout对象,然后在QFormLayout对象中添加控件,最后将该布局放到QGroupBox对象中,代码如下:
//头文件
#include <QFormLayout>
#include <QComboBox>
#include <QSpinBox>
shared_ptr<QGroupBox> formbox_;
shared_ptr<QFormLayout> formlayout_;
shared_ptr<QComboBox> cobobox_;
shared_ptr<QSpinBox> spinbox_;
shared_ptr<QLineEdit> linedit4_;
vector<shared_ptr<QLabel>> labels4_;
//源文件构造函数
, formbox_(make_shared<QGroupBox>(tr("form layout")))
, formlayout_(make_shared<QFormLayout>(this))
, cobobox_(make_shared<QComboBox>(this))
, spinbox_(make_shared<QSpinBox>(this))
, linedit4_(make_shared<QLineEdit>(this))
labels4_.resize(3);
creatformlayout();
mainlayout_->addWidget(formbox_.get());
void Widget::creatformlayout()
{
for (int i=0;i<labels4_.size();++i) {
labels4_[i].reset(new QLabel(tr("line%1").arg(i+1)));
}
int i=0;
formlayout_->addRow(labels4_[i++].get(), linedit4_.get());
formlayout_->addRow(labels4_[i++].get(), cobobox_.get());
formlayout_->addRow(labels4_[i++].get(), spinbox_.get());
formbox_->setLayout(formlayout_.get());
}
效果如下
5.绘制文本框和两个按键
直接使用QDialogButtonBox和QTextEdit生成对象,然后添加到主布局中即可
代码如下
//头文件
#include <QDialogButtonBox>
shared_ptr<QTextEdit> textedit5_;
shared_ptr<QDialogButtonBox> diabtnbox_;
//构造函数代码
, textedit5_(make_shared<QTextEdit>(this))
, diabtnbox_(make_shared<QDialogButtonBox>(QDialogButtonBox::Ok | QDialogButtonBox::Cancel))//添加Ok和Cancel两个button
mainlayout_->addWidget(textedit5_.get());
mainlayout_->addWidget(diabtnbox_.get());
最终整体效果如下
和示例效果基本一致
完整代码见https://gitee.com/cuijidan/qtdemo_basiclayout
https://doc.qt.io/qt-5/qtwidgets-layouts-basiclayouts-example.html
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出