Dynamic Layouts Example
演示如何在运行的应用程序中重新定位小部件。
动态布局在运行的应用程序中实现动态放置的小部件。小部件的位置取决于选择水平还是垂直。
main.cpp
#include <QApplication>
#include "dialog.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Dialog dialog;
#ifdef Q_OS_ANDROID
dialog.showMaximized();
#else
dialog.show();
#endif
return app.exec();
}
Dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QtWidgets>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
private slots:
void buttonsOrientationChanged(int index);
void rotateWidgets();
void help();
private:
void createRotatableGroupBox();
void createOptionsGroupBox();
void createButtonBox();
QGroupBox *rotatableGroupBox;
QQueue<QWidget *> rotatableWidgets;
QGroupBox *optionsGroupBox;
QLabel *buttonsOrientationLabel;
QComboBox *buttonsOrientationComboBox;
QDialogButtonBox *buttonBox;
QPushButton *closeButton;
QPushButton *helpButton;
QPushButton *rotateWidgetsButton;
QGridLayout *mainLayout;
QGridLayout *rotatableLayout;
QGridLayout *optionsLayout;
};
#endif // DIALOG_H
Dialog.cpp
#include <QtWidgets>
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
createRotatableGroupBox();
createOptionsGroupBox();
createButtonBox();
mainLayout = new QGridLayout;
mainLayout->addWidget(rotatableGroupBox, 0, 0);
mainLayout->addWidget(optionsGroupBox, 1, 0);
mainLayout->addWidget(buttonBox, 2, 0);
setLayout(mainLayout);
mainLayout->setSizeConstraint(QLayout::SetMinimumSize);
setWindowTitle(tr("Dynamic Layouts"));
}
// 槽函数 垂直和水平布局的变化
void Dialog::buttonsOrientationChanged(int index)
{
mainLayout->setSizeConstraint(QLayout::SetNoConstraint);
setMinimumSize(0, 0);
Qt::Orientation orientation = Qt::Orientation(
buttonsOrientationComboBox->itemData(index).toInt());
if (orientation == buttonBox->orientation()) // buttonBox的方向
return;
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 Dialog::rotateWidgets()
{
Q_ASSERT(rotatableWidgets.count() % 2 == 0); // 必须是偶数
for (QWidget *widget : qAsConst(rotatableWidgets))
rotatableLayout->removeWidget(widget); // 先从布局删除
rotatableWidgets.enqueue(rotatableWidgets.dequeue()); // 把头放入尾部
const int n = rotatableWidgets.count();
for (int i = 0; i < n / 2; ++i) { // 按修改后的顺序进行网格布局,实现了旋转功能
rotatableLayout->addWidget(rotatableWidgets[n - i - 1], 0, i);
rotatableLayout->addWidget(rotatableWidgets[i], 1, i);
}
}
void Dialog::help()
{
QMessageBox::information(this, tr("Dynamic Layouts Help"),
tr("This example shows how to change layouts "
"dynamically."));
}
/* 创建一个可旋转的组框,然后添加QSpinBox、QSlider、QDial、QProgressBar */
void Dialog::createRotatableGroupBox()
{
rotatableGroupBox = new QGroupBox(tr("Rotatable Widgets"));
rotatableWidgets.enqueue(new QSpinBox); // 加入到rotatableWidgets队列
rotatableWidgets.enqueue(new QSlider);
rotatableWidgets.enqueue(new QDial);
rotatableWidgets.enqueue(new QProgressBar);
int n = rotatableWidgets.count();
for (int i = 0; i < n; ++i) { // 技巧:将当前控件的信号 关联到 其他控件的槽函数
connect(rotatableWidgets[i], SIGNAL(valueChanged(int)),
rotatableWidgets[(i + 1) % n], SLOT(setValue(int)));
}
rotatableLayout = new QGridLayout;
rotatableGroupBox->setLayout(rotatableLayout);
rotateWidgets();
}
/* 创建选项组 一个标签、一个组合框 */
void Dialog::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);
connect(buttonsOrientationComboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &Dialog::buttonsOrientationChanged);
optionsLayout = new QGridLayout;
optionsLayout->addWidget(buttonsOrientationLabel, 0, 0);
optionsLayout->addWidget(buttonsOrientationComboBox, 0, 1);
optionsLayout->setColumnStretch(2, 1);
optionsGroupBox->setLayout(optionsLayout);
}
/* 创建按钮组 对话框按钮组 */
void Dialog::createButtonBox()
{
buttonBox = new QDialogButtonBox;
closeButton = buttonBox->addButton(QDialogButtonBox::Close); //标准关闭按钮
helpButton = buttonBox->addButton(QDialogButtonBox::Help); //标准帮助按钮
rotateWidgetsButton = buttonBox->addButton(tr("Rotate &Widgets"), //标准操作按钮
QDialogButtonBox::ActionRole);
connect(rotateWidgetsButton, &QPushButton::clicked, this, &Dialog::rotateWidgets);
connect(closeButton, &QPushButton::clicked, this, &Dialog::close);
connect(helpButton, &QPushButton::clicked, this, &Dialog::help);
}
总结
QGridLayout 这个布局使用起来非常方便,由此例可见一斑。