15.QT布局管理及示例

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

水平布局主要是用到了QGroupBoxQHBoxLayout,将四个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

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值