采用绝对定位的开发方式,组件的位置和大小无法自适应父窗口的变化。
提供相关的类对界面组件进行布局管理
QLayout 是 Qt 中布局管理器的抽象基类
通过继承 QLayout 实现功能各异且互补的布局管理器
Qt 中可以根据需要自定义布局管理器
布局管理器不是界面部件,而是界面部件的定位策略
以水平或垂直的方式管理界面组件
默认情况下以等比例的方式更新组件大小
可以自定义组件大小更新时的比例系数
void setStretch(int index,int stretch)
void setStretchFactor(Qwidget* widget,int stretch)
void setStretchFactor(QLayout* layout,int stretch)
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);
}
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);
}
布局管理器可以相互嵌套,形成更加复杂的布局方式
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);
}
组件的初始化大小是独立于布局管理器设置的,因此不能保证组件的大小始终符合比例系数的设置!
以网格 (二维) 的方式管理界面组件
void setColumnStretch(int column,int stretch)
void setRowStretch(int row,int stretch)
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);
}
QGridLayout 支持嵌套其他布局管理器成为其管理对象
以表单 (form) 的方式管理界面组件
表单布局中的标签和组件是相互对应的关系
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)
表单布局支持嵌套,其他布局管理器可以作为子布局被其管理
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");
}
所有组件在垂直于屏幕的方向上被管理
每次只有一个组件会显示在屏幕上
只有最顶层的组件会被最终显示
组件大小一致且充满父组件的显示区
不能直接嵌套其它布局管理器
能够自由切换需要显示的组件
每次能且仅能显示一个组件
int addWidget(QWidget* widget)
QWidget* currentWidget()
void setCurrentIndex(int index)
int currentIndex()
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 对象设置布局管理器的方法间接添加布局管理器。
任何容器类的组件都可以指定布局管理器
同一个布局管理器中的组件拥有相同的父组件
设置布局管理器的同时隐式的指定了父子关系
图中组件1和组件2被同一个布局管理器管理,拥有相同的父组件 。