Qt中的动态布局(Dynamic Layout)

Qt中的动态布局

主要注意下面两点
一、QGroupBox组合框中添加控件

在QGroupBox组合框中加入控件,需要先把其它子控件使用布局结合在一起,
然后再调用QGroupBox::setLayout()函数,添加该布局。
即实现了把子控件添加到QGroupBox组合框中
//QGroupBox::setLayout()

二、动态布局

在布局类中调用removeWidget(); //删除布局中的子控件,
再在布局类中调用addWidget(); //添加子控件
即可实现动态布局
//mainLayout->removeWidget();
//mainLayout->addWidget();


下面给出代码示例

//.h文件

#include <QWidget>
#include <QtGui>

class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = 0);

private:
    //函数部分
    //创建第一部分界面:旋转控件组合框
    void createRotableGroupBox();
    //创建第二部分界面:方向组合框
    void createOptionsGroupBox();
    //创建第三部分界面:按钮组合框
    void createButtonBox();

    //控件部分
    //第一部分:QGroupBox控件
    QGroupBox *rotableGroupBox;
    QQueue<QWidget *> rotableWidgets;   //控件队列

    //第二部分:QGroupBox控件
    QGroupBox *optionsGroupBox;
    QLabel *buttonsOrientationLabel;
    QComboBox *buttonsOrientationComboBox;

    //第三部分:QDialogButtonBox控件
    QDialogButtonBox *buttonBox;
    QPushButton *closeButton;
    QPushButton *helpButton;
    QPushButton *rotateWidgetsButton;

    //布局
    //总体布局
    QGridLayout *mainLayout;
    //第一部分中的控件布局
    QGridLayout *rotableLayout;
    //第二部分中的控件布局
    QGridLayout *optionsLayout;

signals:

public slots:
    //QComboBox中index改变产生currentIndexChanged()信号对应的槽函数
    void buttonsOrientationChanged(int index);
    //构建rotableGroupBox组合框中的四个子控件的动态布局
    void rotateWidgets();
    void help();

};

//.cpp文件

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent)
{
    createRotableGroupBox();
    createOptionsGroupBox();
    createButtonBox();

    mainLayout = new QGridLayout;
    //主布局中添加3个组合框控件
    mainLayout->addWidget(rotableGroupBox, 0, 0);
    mainLayout->addWidget(optionsGroupBox, 1, 0);
    mainLayout->addWidget(buttonBox, 2, 0);
    setLayout(mainLayout);

    //布局的大小限制(Constraint)模式:设置最小大小
    mainLayout->setSizeConstraint(QLayout::SetMinimumSize);

    setWindowTitle(tr("Dynamic layouts"));
}


void MyWidget::createRotableGroupBox()
{
    rotableGroupBox = new QGroupBox(tr("Rotable Widgets"));

    rotableWidgets.enqueue(new QSpinBox);   //微调器入队
    rotableWidgets.enqueue(new QSlider);    //滑块
    rotableWidgets.enqueue(new QDial);  //刻度盘
    rotableWidgets.enqueue(new QProgressBar);   //进度条

    //子控件个数
    int n = rotableWidgets.count();

    //四个控件首尾相连,关系形成一个环形,一个控件的数值改变随之后面的控件也改变
    for(int i=0; i<n; ++i)
    {
        connect(rotableWidgets[i], SIGNAL(valueChanged(int)),
                rotableWidgets[(i+1)%n], SLOT(setValue(int)));
    }

    rotableLayout = new QGridLayout;

    //QGroupBox组合框控件,组合框控件中加入其它子控件,
    rotableGroupBox->setLayout(rotableLayout);

    //构建rotableGroupBox组合框中的四个子控件的动态布局
    rotateWidgets();
}


void MyWidget::rotateWidgets()
{
    //断言
    Q_ASSERT(rotableWidgets.count()%2 == 0);

    //按顺序遍历容器中的对象,遍历队列中的控件
    foreach(QWidget *widget, rotableWidgets)
        rotableLayout->removeWidget(widget);    //删除布局中的子控件,动态布局

    //控件队列中的头部控件出队后,入队尾
    rotableWidgets.enqueue(rotableWidgets.dequeue());

    const int n = rotableWidgets.count();   //4
    for(int i=0; i<n/2; ++i)
    {
        //添加控件到布局类中,动态布局,交换控件显示的位置
        rotableLayout->addWidget(rotableWidgets[n-i-1], 0, i);  //3,(0,0)   2,(0,1)
        rotableLayout->addWidget(rotableWidgets[i], 1, i);  //0,(1,0)   1,(1,1)
    }
}


void MyWidget::createOptionsGroupBox()
{
    optionsGroupBox = new QGroupBox(tr("Options"));

    buttonsOrientationLabel = new QLabel(tr("Orientation of buttons:"));

    buttonsOrientationComboBox = new QComboBox;
    buttonsOrientationComboBox->addItem(tr("Horizontal"), Qt::Horizontal);
    buttonsOrientationComboBox->addItem(tr("Vertical"), Qt::Vertical);

    //QComboBox中的索引值(index)改变的信号连接到槽函数
    connect(buttonsOrientationComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(buttonsOrientationChanged(int)));

    optionsLayout = new QGridLayout;
    optionsLayout->addWidget(buttonsOrientationLabel, 0, 0);
    optionsLayout->addWidget(buttonsOrientationComboBox, 0, 1);
    //设置第二列的延伸属性(strech factor)
    optionsLayout->setColumnStretch(2,1);
    optionsGroupBox->setLayout(optionsLayout);
}


void MyWidget::buttonsOrientationChanged(int index)
{
    mainLayout->setSizeConstraint(QLayout::SetNoConstraint);
    setMinimumSize(0,0);

    //获取QComboBox中的方向信息
    Qt::Orientation orientation = Qt::Orientation(
                buttonsOrientationComboBox->itemData(index).toInt());

    //判断方向是否改变
    if(orientation == buttonBox->orientation())
        return;

    //控制buttonBox的布局
    mainLayout->removeWidget(buttonBox);

    int spacing = mainLayout->spacing();

    QSize oldSizeHint = buttonBox->sizeHint() + QSize(spacing, spacing);
    //设置按钮框的布局方向
    buttonBox->setOrientation(orientation);
    QSize newSizeHint = buttonBox->sizeHint() + QSize(spacing, spacing);

    if(orientation == Qt::Horizontal)
    {
        mainLayout->addWidget(buttonBox, 2, 0);
        resize(size() + QSize(-oldSizeHint.width(), newSizeHint.height()));
    }
    else
    {
        mainLayout->addWidget(buttonBox, 0, 3, 2, 1);
        resize(size() + QSize(newSizeHint.width(), -oldSizeHint.height()));
    }

    mainLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
}


void MyWidget::createButtonBox()
{
    buttonBox = new QDialogButtonBox;

    closeButton = buttonBox->addButton(QDialogButtonBox::Close);
    helpButton = buttonBox->addButton(QDialogButtonBox::Help);
    rotateWidgetsButton = buttonBox->addButton(tr("Rotate &Widgets"),
                                               QDialogButtonBox::ActionRole);

    connect(rotateWidgetsButton, SIGNAL(clicked()), this, SLOT(rotateWidgets()));
    connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(helpButton, SIGNAL(clicked()), this, SLOT(help()));
}


void MyWidget::help()
{
    QMessageBox::information(this, tr("Dynamic Layouts Help"),
                             tr("This example shows how the change layouts dynamically."));
}

实现效果如下图:
这里写图片描述

这里写图片描述


代码来源于Qt官网,
链接:http://doc.qt.io/qt-5/qtwidgets-layouts-dynamiclayouts-example.html

猜你喜欢

转载自blog.csdn.net/u011125673/article/details/52025081