Layout

作者: downdemo | 来源:发表于2018-08-16 14:59 被阅读40次

    QLayout
    QBoxLayout
    QGridLayout
    QFormLayout
    All Layout
    QMargins

    简介

    • Qt布局使用很简单
    // main.cpp
    QVBoxLayout* layout = new QVBoxLayout(this);
    
    layout->setMenuBar(menuBar);
    layout->addWidget(tabWidget);
    layout->addWidget(label2);
    
    w.setLayout(layout);
    w.show();
    
    • 可以看到三个控件依次纵向排列(右侧是写好的窗口,同样是垂直布局)
    • 且拉伸窗口时将自适应变化
    • 注意,菜单栏设置布局使用的是setMenuBar,如果用addWidget效果如下
    • 不在main.cpp而在窗口的构造函数中直接添加控件实现时,发现布局不起作用,原因在于窗口有一个中央窗体,必须使用setCentralWidget在此之上布局
    QWidget* centralWidget = new QWidget();
    centralWidget->setLayout(layout);
    setCentralWidget(centralWidget);
    
    • 完整的实现
    // tabtest.cpp(即MainWindow.cpp)
    #include "tabtest.h"
    
    tabtest::tabtest(QWidget *parent)
        : QMainWindow(parent)
    {
        ui.setupUi(this);
    
        // 菜单栏,因为使用了布局所以setGeometry会失效
        menuBar = new QMenuBar(this);
        // menuBar->setGeometry(QRect(0, 0, 400, 24));
        QMenu* menu = menuBar->addMenu(tr("&File"));
        actionNew = menu->addAction(tr("&New"));
        actionNew->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));
    
        // 左侧导航
        tabWidget = new QTabWidget(this);
        dlg = new dlg1();
        QLabel *label = new QLabel();
        label->setText(u8"测试2");
        tabWidget->addTab(dlg, u8"页面1");
        tabWidget->addTab(label, u8"页面2");
        tabWidget->setTabPosition(QTabWidget::West);
        // tabWidget->setGeometry(QRect(0, 0, width(), height()));
        tabWidget->tabBar()->setStyle(new CustomTabStyle);
    
        // 最下方的一个label
        QLabel *label2 = new QLabel();
        label2->setText(u8"test label");
    
        // 垂直布局
        QVBoxLayout* layout = new QVBoxLayout;
        layout->setMenuBar(menuBar);
        layout->addWidget(tabWidget);
        layout->addWidget(label2);
    
        QWidget *centralWidget = new QWidget;
        centralWidget->setLayout(layout);
        setCentralWidget(centralWidget);
    }
    
    • 布局也能直接用addLayout嵌套
    QHBoxLayout* layout1 = new QHBoxLayout(this);
    QVBoxLayout* layout2 = new QVBoxLayout(this);
    ... // layout1添加内容
    layout2->addLayout(layout1); // 把layout1的横排布局作为一个内容
    ... // layout2再添加其他内容
    

    几种布局

    • 所有的布局管理器
    QHBoxLayout:水平方向从左到右
    QVBoxLayout:竖直方向从上到下
    QGridLayout:栅格布局
    QFormLayout:表格布局,每一行前面是一段文本,文本后接一个组件(通常是输入框)
    QStackedLayout:层叠布局,允许组件 Z 轴层叠,做出类似于tabWidget效果
    
    // 设置控件比例
    void QBoxLayout::setStretch(int index, int stretch);
    // 第一个参数为控件索引,第二个为延伸值
    layout1->setStretch(0, 1);
    layout1->setStretch(1, 2);
    // 这样两个控件的比例为1:2,分别设置为5,10结果也一样
    
    // 末尾填充,实现控件靠左
    void QBoxLayout::addStretch(int stretch = 0); // 参数设置为1即可
    
    // 在对应索引位置插入填充
    void QBoxLayout::insertStretch(int index, int stretch = 0);
    
    // 设置控件间隔
    void QBoxLayout::setSpacing(int spacing);
    
    // 在对应索引位置设置间隔
    void QBoxLayout::insertSpacing(int index, int size);
    
    // 利用QSpacerItem作为间隔
    // 后两个参数是大小调整策略
    QSpacerItem(int *w*, int *h*,
        QSizePolicy::Policy *hPolicy* = QSizePolicy::Minimum,
        QSizePolicy::Policy *vPolicy* = QSizePolicy::Minimum)
    
    void QBoxLayout::addSpacerItem(QSpacerItem *spacerItem);
    void QBoxLayout::insertSpacerItem(int index, QSpacerItem *spacerItem);
    // 空隙尽可能扩展
    layout->addSpacerItem(new QSpacerItem(20, 20, QSizePolicy::Expanding));
    
    • 移除
    while (layout->count())
        layout->removeItem(layout->itemAt(layout->count()-1));
    // 也可以用removeWidget
    while (layout->count())
        layout->removeWidget(layout->itemAt(layout->count()-1)->widget());
    
    void addItem(QLayoutItem *item, int row, int column,
        int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = ...);
    void addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment = ...);
    void addLayout(QLayout *layout, int row, int column,
        int rowSpan, int columnSpan, Qt::Alignment alignment = ...);
    
    void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment = ...);
    void addWidget(QWidget *widget, int fromRow, int fromColumn,
        int rowSpan, int columnSpan, Qt::Alignment alignment = ...);
    
    void setHorizontalSpacing(int spacing);
    void setVerticalSpacing(int spacing);
    
    void setRowStretch(int row, int stretch); // 设置某行的比例
    void setColumnStretch(int column, int stretch);
    
    void setRowMinimumHeight(int row, int minSize);
    void setColumnMinimumWidth(int column, int minSize);
    
    • 让控件占QGridLayout的多个单元格
    btn1->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    btn2->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    btn3->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    mainLayout->addWidget(btn1, 0, 0, 1, 1); // btn1在位置(0, 0)并占1行1列
    mainLayout->addWidget(btn2, 0, 1, 1, 1); // btn2在位置(0, 1)并占1行1列
    mainLayout->addWidget(btn3, 1, 0, 1, 2); // btn在位置(1, 0)并占1行2列
    
    效果图
    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);
    void addRow(QWidget *widget);
    void addRow(QLayout *layout);
    
    void insertRow(int row, QWidget *label, QWidget *field);
    void insertRow(int row, QWidget *label, QLayout *field);
    void insertRow(int row, const QString &labelText, QWidget *field);
    void insertRow(int row, const QString &labelText, QLayout *field);
    void insertRow(int row, QWidget *widget);
    void insertRow(int row, QLayout *layout);
    
    void removeRow(int row);
    void removeRow(QWidget *widget);
    void removeRow(QLayout *layout);
    
    void setFieldGrowthPolicy(QFormLayout::FieldGrowthPolicy policy); // 设置控件大小策略
    
    Constant Value Description
    QFormLayout::FieldsStayAtSizeHint 0 可以被拉伸不超过SizeHint值,这是QMacStyle的默认值
    QFormLayout::ExpandingFieldsGrow 1 大小策略设置了水平的Expanding或MinimumExpanding的控件被尽可能拉伸占满布局,其他同FieldsStayAtSizeHint
    QFormLayout::AllNonFixedFieldsGrow 2 全部可以被拉伸占满布局,是大多数样式的默认策略
    • 设置间距
    // QBoxlayout
    void setSpacing(int spacing);
    
    // QGridLayout和QFormLayout
    void setHorizontalSpacing(int spacing);
    void setVerticalSpacing(int spacing);
    

    QLayout通用

    • 通过setSizeConstraint设置大小约束
    void setSizeConstraint(QLayout::SizeConstraint)
    
    Constant Value Description
    QLayout::SetDefaultConstraint 0 The main widget's minimum size is set to minimumSize(), unless the widget already has a minimum size.
    QLayout::SetFixedSize 3 The main widget's size is set to sizeHint(); it cannot be resized at all.
    QLayout::SetMinimumSize 2 The main widget's minimum size is set to minimumSize(); it cannot be smaller.
    QLayout::SetMaximumSize 4 The main widget's maximum size is set to maximumSize(); it cannot be larger.
    QLayout::SetMinAndMaxSize 5 The main widget's minimum size is set to minimumSize() and its maximum size is set to maximumSize().
    QLayout::SetNoConstraint 1 The widget is not constrained.
    • 通过setContentsMargins设置边距
    void setContentsMargins(int left, int top, int right, int bottom);
    void QLayout::setContentsMargins(const QMargins &margins);
    
    QMargins(int left, int top, int right, int bottom)
    

    QLayout: Attempting to add QLayout XXX to XXX, which already has a layout

    • 此警告原因在于多次使用setLayout
    btn1 = new QPushButton(this); // 1
    btn1->setText("test");
    QHBoxLayout* layout = new QHBoxLayout(this); // 2
    layout->addWidget(btn1);
    
    QWidget* centralWidget = new QWidget(this);
    centralWidget->setLayout(layout); // 3
    setCentralWidget(centralWidget);
    
    • 1和2两次用this隐式设置了窗口布局,3又再次显式使用setLayout,解决方法是删掉2的this,或不使用3的setLayout方法

    相关文章

      网友评论

          本文标题:Layout

          本文链接:https://www.haomeiwen.com/subject/twfobftx.html