文章目录
QT主要布局类型
QT中主要提供了QLayout类及其子类作为布局管理器,如下图所示主要的布局类及其继承关系
所有的QWidget类的子类的实例都可以使用布局管理器来管理位于它们之中的子部件,QWidget::setLayout()函数可以在一个部件上应用布局管理器。
一旦一个部件上设置了布局管理器,那么它会完成以下几种任务:
- 定位子部件
- 感知窗口默认大小
- 感知窗口最小大小
- 改变大小处理
- 内容改变时自动更新:字体大小,文本或子部件的其他内容随之改变、隐藏或显示子部件、移除子部件
- 当部件加入到一个布局管理器中,然后这个布局管理器再放到一个窗口部件上时,这个布局管理器以及它包含的所有部件都会自动重新定义自己的父对象(parent)为这个窗口部件,所以在创建布局管理器和其中的部件时并不用指定父部件。
布局管理器
QLayout类是布局管理器的基类,它是一个抽象基类。该类继承自QObject和QLayoutItem类,而QLayoutItem类提供了一个供QLayout操作的抽象项目。 QLayout和QLayoutItem都是在设计自己的布局管理器时才使用,有一些常用的布局管理器:
- QBoxLayout(基本布局管理器)
- QGridLayout(栅格布局管理器)
- QFormLayout(窗体布局管理器)
- QStackedLayout(栈布局管理器)
下面详细介绍每一个布局管理器,以及如何使用。
QBoxLayout(基本布局管理器)
基本布局管理器QBoxLayout类可以使子部件在水平方向或者垂直方向排成一列,它有两个子类QHBoxLayout水平布局管理器和QVBoxLayout垂直布局管理器。
- QHBoxLayout:水平布局,放入此布局的部件,将按照水平方式排列
- QVBoxLayout:垂直布局,放入此布局的部件,将按照垂直方式排列
以下是一些基本属性的设置:
QHBoxLayout *layout = new QHBoxLayout; // 新建水平布局管理器
layout->addWidget(ui->textEdit); // 向布局管理器中添加部件
layout->setSpacing(50); // 设置部件间的间隔,所有的部件之间都是这个间距
layout->setContentsMargins(0, 0, 50, 100); // 设置布局管理器到边界的距离,
// 四个参数顺序是左,上,右,下
layout->addSpacing(50); // 与setSpacing不一样,仅仅是前后两个的间距
layout->addStretch(); // 增加一个可伸缩空间
setLayout(layout); // 在父窗口添加布局管理器
QGridLayout(栅格布局管理器)
栅格布局管理器,它将所有的空间分隔成一些行和列,行和列的交叉处就形成了单元格,然后将部件放入一个确定的单元格中,示例代码如下:
QGridLayout *layout = new QGridLayout;
// 添加部件,从第0行0列开始,占据1行2列
layout->addWidget(ui->fontComboBox, 0, 0, 1, 2);
// 添加部件,从第0行2列开始,占据1行1列
layout->addWidget(ui->pushButton, 0, 2, 1, 1);
// 添加部件,从第1行0列开始,占据1行3列
layout->addWidget(ui->textEdit, 1, 0, 1, 3);
setLayout(layout);
QFormLayout(表单布局管理器)
表单布局管理器QFormLayout类用来管理表单的输入部件和与它们相关的标签,它将子部件分为两列,左边是一些标签,右边是一些输入部件,比如行编辑器或者数字选择框等,左右两边有对应关系。
在设计模式,从部件栏中找到Form Layout,将其拖入到界面上,然后双击它,或者在它上面点击鼠标右键,选择“添加窗体布局行”菜单。
然后在弹出的“添加表单布局行”对话框中填入标签文字,这样下面便自动填写了“标签名称”、“字段类型”和“字段名称”等,并且设置了伙伴关系。
伙伴关系表示当按下“Alt+设置标签的快捷字母,即(&符号后面的字母)“”时,光标会自动跳转到标签后面对应的行编辑器中。
QStackedLayout(栈式布局管理器)
QStackedLayout栈式布局管理器管理的所有组件在垂直于屏幕的方向上,每次只有一个界面组件会显示在屏幕上,只要最顶层的界面组件会被显示。 QStackedLayout栈式布局管理器的特点如下:
- 组件大小一致,且充满父组件的显示区
- 不能直接嵌套其它布局管理器
- 能够*切换需要显示的组件
- 每次仅能显示一个界面组件
void LayoutWidget::StackedLayout()
{
//创建组件并设置显示标签
QPushButton *button1 = new QPushButton();
QPushButton *button2 = new QPushButton();
QPushButton *button3 = new QPushButton();
QPushButton *button4 = new QPushButton();
button1->setText("1st");
button2->setText("2rd");
button3->setText("3th");
button4->setText("4th");
//创建栈式布局管理器并添加组件
sLayout = new QStackedLayout();
sLayout->addWidget(button1);
sLayout->addWidget(button2);
sLayout->addWidget(button3);
sLayout->addWidget(button4);
//设置当前栈顶显示的组件
connect(button1, &QPushButton::clicked, this, &LayoutWidget::btn1_clicked);
connect(button2, &QPushButton::clicked, this, &LayoutWidget::btn2_clicked);
connect(button3, &QPushButton::clicked, this, &LayoutWidget::btn3_clicked);
connect(button4, &QPushButton::clicked, this, &LayoutWidget::btn4_clicked);
sLayout->setCurrentIndex(0);
//设置栈式布局管理器到窗口
setLayout(sLayout);
}
void LayoutWidget::btn1_clicked()
{
sLayout->setCurrentIndex(1);
}
void LayoutWidget::btn2_clicked()
{
sLayout->setCurrentIndex(2);
}
void LayoutWidget::btn3_clicked()
{
sLayout->setCurrentIndex(3);
}
void LayoutWidget::btn4_clicked()
{
sLayout->setCurrentIndex(0);
}
QSplitter(分裂器)
它和QBoxLayout很相似,可以完成布局管理器的功能,但是包含在它里面的部件,默认是可以随着分裂器的大小变化而进行相应大小变化的。QSplitter有以下特点
- 一个按钮,放在布局管理器中,它的垂直方向默认是不会被拉伸的,但是放到分裂器中就可以被拉伸
- 布局管理器是继承自QObject类的,而分裂器却是继承自QFrame类,QFrame类又是继承自QWidget类,也就是说分裂器拥有QWidget类的特性,它是可见的,而且可以像QFrame一样设置边框。
- 分离器能通过鼠标拖拽调整两个窗口的大小
QSplitter *splitterMain = new QSplitter(Qt::Horizontal,0);
QTextEdit *textLeft = new QTextEdit(QObject::tr("Left Widget"),splitterMain);
textLeft->setAlignment(Qt::AlignCenter);
//右部分分割窗口
QSplitter *splitterRight = new QSplitter(Qt::Vertical,splitterMain);
splitterRight->setOpaqueResize(true);
//表示分割窗口拖拽时边界是否实时显示
QTextEdit *textUp = new QTextEdit(QObject::tr("Top Widget"),splitterRight);
textUp->setAlignment(Qt::AlignCenter);
QTextEdit *textBottom = new QTextEdit(QObject::tr("Bottom Widget"),splitterRight);
textBottom->setAlignment(Qt::AlignCenter);
splitterMain->setStretchFactor(1,1);
//SetStretchFactor()方法用于设定可伸缩控件,它的第一个参数指定设置的控件序号,
//控件序号按插入的先后次序进行编号;第二个参数为大于0的值表示此控件为可伸缩控件。
splitterMain->setWindowTitle(QObject::tr("Splitter"));
布局策略
设置部件大小
凡是继承自QWidget的类都有这两个属性:大小提示(sizeHint)和最小大小提示(minimumSizeHint)。
- sizeHint属性保存了部件的建议大小,对于不同的部件,默认拥有不同的sizeHint,程序中使用sizeHint()函数来获取sizeHint的值
- minimumSizeHint保存了一个建议的最小大小。程序中可以使用minimumSizeHint()函数来获取minimumSizeHint的值 。
- 如果使用minimumSize()函数设置了部件的最小大小,那么最小大小提示将会被忽略。
部件大小的策略属性有以下几种选择
伸缩因子 stretch factor
它是用来设置部件间的比例的。
例如,界面上的字体选择框和一个按钮处于一个水平布局管理器中,现在想让它们的宽度比例为2:1,
那么就可以点击对象栏中的horizontalLayout水平布局管理器对象,然后在它的属性栏中将layoutStretch属性设置为“2,1”,这样这个水平布局管理器中的两个部件的宽度就是2:1的比例了。
如果要在代码中进行设置,可以在使用布局管理器的addWidget()函数添加部件的同时,在第二个参数中指定伸缩因子。
设置伙伴关系
伙伴(buddy)是在QLabel类中提出的一个概念。
因为一个标签经常用作一个交互式部件的说明,就像表单布局管理器时看到的那样,一个lineEdit部件前面有一个标签说明这个lineEdit的作用。为了方便定位,QLabel提供了一个有用的机制,那就是提供了助记符来设置键盘焦点到对应的部件上,而这个部件就叫做这个QLabel的伙伴。
其中助记符就是我们所说的加速键。在使用英文标签时,在字符串的一个字母前面添加“&”符号,那么就可以指定这个标签的加速键是Alt加上这个字母,而对于中文,需要在小括号中指定加速键字母。
设置TAB键顺序
对于一个应用程序,当希望使用Tab键来将焦点从一个部件移动到下一个部件。在设计模式,设计器提供了Tab键的设置功能。在UI设计模式中,按下上边栏的编辑Tab顺序按钮进入编辑Tab键顺序模式,这时已经显示出了各个部件的Tab键顺序,只需要用鼠标点击这些数字,就可以更改它们。
代码实现方式如下:
//lineEdit在spinBox前面
setTabOrder(ui->lineEdit,ui->spinBox);
//spinBox在pushButton前面
setTabOrder(ui->spinBox,ui->pushButton);
//pushButton在checkBox前面
setTabOrder(ui->pushButton,ui->checkBox);
整体与局部布局
对于一个APP应用,需要最开始框架一层层深入到交互的每一层窗口,每个窗口使用哪些部件元素,如何布局,需要花一点心思,但是总体思路是框架设计由整体到局部,布局细化由局部到整体,尽量在每一层的局部就把布局昨晚,这样每一层只关心同等层次的布局,与软件开发类似。
本篇文章借用了QT社区的一些内容,欢迎访问Qt开源社区