布局管理器

采用绝对定位的开发方式,组件的位置和大小无法自适应父窗口的变化。

解决方案:布局管理器

提供相关的类对界面组件进行布局管理

  • 能够自动排列窗口中的界面组件
  • 窗口变化后自动更新界面组件的大小

QLayout

QLayout 是 Qt 中布局管理器的抽象基类

通过继承 QLayout 实现功能各异且互补的布局管理器

Qt 中可以根据需要自定义布局管理器

布局管理器不是界面部件,而是界面部件的定位策略

布局管理器_第1张图片

QBoxLayout 布局管理器

以水平或垂直的方式管理界面组件

布局管理器_第2张图片

布局管理器_第3张图片

布局管理器中的比例系数

默认情况下以等比例的方式更新组件大小

可以自定义组件大小更新时的比例系数 

QBoxLayout 中的比例系数设置

void setStretch(int index,int stretch)

void setStretchFactor(Qwidget* widget,int stretch)

void setStretchFactor(QLayout* layout,int stretch)

QVBoxLayout 使用示例

void Widget::testVBoxLayout(void)
{
    QVBoxLayout *layout = new QVBoxLayout(this);

    TextBtn1.setMinimumSize(160, 30);
    TextBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn1.setText("Test Button 1");

    TextBtn2.setMinimumSize(160, 30);
    TextBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn2.setText("Test Button 2");

    TextBtn3.setMinimumSize(160, 30);
    TextBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn3.setText("Test Button 3");

    TextBtn4.setMinimumSize(160, 30);
    TextBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn4.setText("Test Button 4");

    layout->setSpacing(30);
    layout->addWidget(&TextBtn1);
    layout->addWidget(&TextBtn2);
    layout->addWidget(&TextBtn3);
    layout->addWidget(&TextBtn4);

    layout->setStretch(0, 1);
    layout->setStretch(1, 1);
    layout->setStretch(2, 2);
    layout->setStretch(3, 2);

    setLayout(layout);
}

布局管理器_第4张图片

QHBoxLayout 使用示例

void Widget::testHBoxLayout(void)
{
    QHBoxLayout *layout = new QHBoxLayout(this);

    TextBtn1.setMinimumSize(160, 30);
    TextBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn1.setText("Test Button 1");

    TextBtn2.setMinimumSize(160, 30);
    TextBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn2.setText("Test Button 2");

    TextBtn3.setMinimumSize(160, 30);
    TextBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn3.setText("Test Button 3");

    TextBtn4.setMinimumSize(160, 30);
    TextBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn4.setText("Test Button 4");

    layout->setSpacing(30);
    layout->addWidget(&TextBtn1);
    layout->addWidget(&TextBtn2);
    layout->addWidget(&TextBtn3);
    layout->addWidget(&TextBtn4);

    layout->setStretchFactor(&TextBtn1, 1);
    layout->setStretchFactor(&TextBtn2, 2);
    layout->setStretchFactor(&TextBtn3, 3);
    layout->setStretchFactor(&TextBtn4, 4);

    setLayout(layout);
}

布局管理器_第5张图片

布局管理器可以相互嵌套,形成更加复杂的布局方式

  • 布局嵌套几乎可以完成所有常用的界面布局
  • 自定义布局类可以达到个性化界面布局的效果

 布局管理器_第6张图片

QBoxLayout 嵌套示例

void Widget::testVHBoxLayout(void)
{
    QHBoxLayout *hLayout1 = new QHBoxLayout();
    QHBoxLayout *hLayout2 = new QHBoxLayout();
    QVBoxLayout *vLayout = new QVBoxLayout();

    TextBtn1.setMinimumSize(160, 30);
    TextBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn1.setText("Test Button 1");

    TextBtn2.setMinimumSize(160, 30);
    TextBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn2.setText("Test Button 2");

    hLayout1->setSpacing(10);
    hLayout1->addWidget(&TextBtn1);
    hLayout1->addWidget(&TextBtn2);

    TextBtn3.setMinimumSize(160, 30);
    TextBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn3.setText("Test Button 3");

    TextBtn4.setMinimumSize(160, 30);
    TextBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn4.setText("Test Button 4");

    hLayout2->setSpacing(10);
    hLayout2->addWidget(&TextBtn3);
    hLayout2->addWidget(&TextBtn4);

    vLayout->setSpacing(10);
    vLayout->addLayout(hLayout1);
    vLayout->addLayout(hLayout2);

    vLayout->setStretchFactor(hLayout1, 1);
    vLayout->setStretchFactor(hLayout2, 2);

    setLayout(vLayout);
}

布局管理器_第7张图片

组件的初始化大小是独立于布局管理器设置的,因此不能保证组件的大小始终符合比例系数的设置!

QGridLayout 布局管理器

以网格 (二维) 的方式管理界面组件

布局管理器_第8张图片

QGridLayout 中的比例系数设置

void setColumnStretch(int column,int stretch)

void setRowStretch(int row,int stretch)

QGridLayout 示例

void Widget::testGridLayout1(void)
{
    QGridLayout *layout = new QGridLayout(this);

    TextBtn1.setMinimumSize(160, 30);
    TextBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn1.setText("Test Button 1");

    TextBtn2.setMinimumSize(160, 30);
    TextBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn2.setText("Test Button 2");

    TextBtn3.setMinimumSize(160, 30);
    TextBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn3.setText("Test Button 3");

    TextBtn4.setMinimumSize(160, 30);
    TextBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn4.setText("Test Button 4");

    layout->setSpacing(10);
    layout->addWidget(&TextBtn1, 0, 0);
    layout->addWidget(&TextBtn2, 0, 1);
    layout->addWidget(&TextBtn3, 1, 0);
    layout->addWidget(&TextBtn4, 1, 1);

    layout->setRowStretch(0, 1);
    layout->setRowStretch(1, 3);

    layout->setColumnStretch(0, 1);
    layout->setColumnStretch(1, 3);

    setLayout(layout);
}

void Widget::testGridLayout2(void)
{
    QGridLayout *layout = new QGridLayout(this);

    TextBtn1.setMinimumSize(160, 30);
    TextBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn1.setText("Test Button 1");

    TextBtn2.setMinimumSize(160, 30);
    TextBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn2.setText("Test Button 2");

    TextBtn3.setMinimumSize(160, 30);
    TextBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn3.setText("Test Button 3");

    TextBtn4.setMinimumSize(160, 30);
    TextBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TextBtn4.setText("Test Button 4");

    layout->setSpacing(10);
    layout->addWidget(&TextBtn1, 0, 0, 2, 1);
    layout->addWidget(&TextBtn2, 0, 1, 2, 1);
    layout->addWidget(&TextBtn3, 2, 0, 1, 2);
    layout->addWidget(&TextBtn4, 3, 0, 1, 2);

    setLayout(layout);
}

布局管理器_第9张图片

布局管理器_第10张图片

 QGridLayout 支持嵌套其他布局管理器成为其管理对象

布局管理器_第11张图片

QFormLayout 布局管理器

以表单 (form) 的方式管理界面组件

表单布局中的标签和组件是相互对应的关系

布局管理器_第12张图片

QFormLayout 的用法概要

void addRow(QWidget* label,QWidget* field)

void addRow(QWidget* label,QLayout* field)

void addRow(const QString& labelText,QWidget* field)

void addRow(const QString& labelText,QLayout* field)

表单布局支持嵌套,其他布局管理器可以作为子布局被其管理

QFormLayout 的使用示例

Widget::Widget(QWidget *parent)
    : QWidget(parent, Qt::WindowCloseButtonHint)
{
    QFormLayout *layout = new QFormLayout(this);
    QLineEdit *nameEdit = new QLineEdit(this);
    QLineEdit *mailEdit = new QLineEdit(this);
    QLineEdit *addrEdit = new QLineEdit(this);

    layout->setSpacing(10);

    layout->addRow("Name:", nameEdit);
    layout->addRow("Email:", mailEdit);
    layout->addRow("Address:", addrEdit);

    // layout->setRowWrapPolicy(QFormLayout::WrapAllRows);
    layout->setRowWrapPolicy(QFormLayout::WrapLongRows);

    layout->setLabelAlignment(Qt::AlignRight);

    setLayout(layout);
    setWindowTitle("FTP");
}

布局管理器_第13张图片

 栈式布局管理器 (QStackedLayout)

所有组件在垂直于屏幕的方向上被管理

每次只有一个组件会显示在屏幕上

只有最顶层的组件会被最终显示

布局管理器_第14张图片

栈式布局管理器的特点

 组件大小一致且充满父组件的显示区

不能直接嵌套其它布局管理器

能够自由切换需要显示的组件

每次能且仅能显示一个组件

QStackedLayout 的用法概要

int addWidget(QWidget* widget)

QWidget* currentWidget()

void setCurrentIndex(int index)

int currentIndex()

QStackedLayout 的使用示例

void Widget::initControl(void)
{
    QStackedLayout *sLayout = new QStackedLayout(this);
    QHBoxLayout *layout = new QHBoxLayout();
    QWidget *widget = new QWidget(this);

    TextBtn1.setText("1st Button");
    TextBtn2.setText("2rd Button");
    TextBtn3.setText("3th Button");
    TextBtn4.setText("Test Button 4");

    TextBtn2.setParent(widget);
    TextBtn3.setParent(widget);

    layout->addWidget(&TextBtn2);
    layout->addWidget(&TextBtn3);

    widget->setLayout(layout);

    sLayout->addWidget(&TextBtn1); // 0
    sLayout->addWidget(widget);    // 1
    sLayout->addWidget(&TextBtn4); // 2

    sLayout->setCurrentIndex(1);

    setLayout(sLayout);
}

QStackedLayout 可以通过 QWidget 对象设置布局管理器的方法间接添加布局管理器。

注意事项

任何容器类的组件都可以指定布局管理器

同一个布局管理器中的组件拥有相同的父组件

设置布局管理器的同时隐式的指定了父子关系

布局管理器_第15张图片

图中组件1和组件2被同一个布局管理器管理,拥有相同的父组件 。

你可能感兴趣的:(Qt,qt)