Qt-常用控件(3)-多元素控件、容器类控件和布局管理器
1. 多元素控件
Qt 中提供的多元素控件有:
- QListWidget
- QListView
- QTableWidget
- QTableView
- QTreeWidget
- QTreeView
xxWidget 和 xxView 之间的区别,以 QTableWidget 和 QTableView 为例.
- QTableView 是基于 MVC 设计的控件.QTableView 自身不持有数据,使用 QTableView 的时候需要用户创建一个 Model对象(比如 QStandardModel),并且把 Model和QTableView 关联起来.后续修改 Model 中的数据就会影响 QTableView 的显示; 修改QTableView 的显示也会影响到 Model 中的数据(双向绑定).
- QTableWidget 则是 QTableView 的子类,对 Model进行了封装.不需要用户手动创建Model对象,直接就可以往 QTableWidget 中添加数据了.
1.1 QListWidget
使用 QListwidget 能够显示一个纵向的列表,就相当于一个列表形如:
核⼼属性
| 属性 | 说明 |
|---|---|
| currentRow | 当前被选中的是第几行 |
| count | 一共有多少行 |
| sortingEnabled | 是否允许排序 |
| isWrapping | 是否允许换行 |
| itemAlignment | 元素的对齐方式 |
| selectRectVisible | 被选中的元素矩形是否可见 |
| spacing | 元素之间的间隔 |
核心方法
| 方法 | 说明 |
|---|---|
| addltem(const QString& label) addltem(QListWidgetltem*item) | 列表中添加元素. |
| currentltem() | 返回 QListWidgetltem*表示当前选中的元素 |
| setCurrentltem(OListWidgetltem*item) | 设置选中哪个元素 |
| setCurrentRow(int row) | 设置选中第几行的元素 |
| insertltem(const QString& label, int row) insertltem(QListWidgetltem *item, int row) | 在指定的位置插入元素 |
| item(int row) | 返回 QListWidgetltem*表示第 row 行的元素 |
| takeltem(int row) | 删除指定行的元素,返回 QListWidgetltem* 表示是哪个元素被删除了 |
核心信号
| 方法 | 说明 |
|---|---|
| currentltemChanged(QListWidgetltemcurrent,QListWidgetltem old) | 选中不同元素时会触发.参数是当前选中的元素和之前选中的元素: |
| currentRowChanged(int) | 选中不同元素时会触发,参数是当前选中元素的行数 |
| itemClicked(QListWidgetltem* item) | 点击某个元素时触发 |
| itemDoubleClicked(QListWidgetltem*item) | 双击某个元素时触发 |
| itemEntered(QListWidgetltem*item) | 鼠标进入元素时触发 |
在上述介绍中,涉及到一个关键的类,QListwidgetItem这个类表示 QListwidget 中的一个元素核心方法如下,本质上就是一个"文本+图标"构成的.
| 方法 | 说明 |
|---|---|
| setFont | 设置字体 |
| setlcon | 设置图标 |
| setHidden | 设置隐藏 |
| setSizeHint | 设置尺寸 |
| setSelected | 设置是否选中 |
| setText | 设置文本 |
| setTextAlignment | 设置文本对齐方式 |
代码示例: 使用 ListWidget:新增按钮列表中的数据,删除按钮删除列表中的数据
- 在界面上创建一个 ListView,右键=>变形为=> Listwidget,再创建一个 lineEdit 和 两个按钮
注意:ListWidget 是 ListView 的子类,功能比 ListView 更丰富.咱们使用Listwidget 即可

- 编写 widget.cpp, 在构造函数中添加初始元素
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->listWidget->addItem("C++");ui->listWidget->addItem("Java");ui->listWidget->addItem("Python");
}
- 编写 listWidget的 slot 函数
此处需要判定 current 和 previous 非空.初始情况下是没有元素选中的,就导致这俩指针可能是 NULL.
// 通过ListWidget的信号感受的发生的变化
void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{if(current !=nullptr){qDebug()<<"当前选中的元素"<<current->text();}if(previous != nullptr){qDebug()<<"上次选中的元素"<<previous->text();}
}
- 编写按钮的 slot 函数
void Widget::on_pushButton_insert_clicked()
{// 先获取框中的内容QString s=ui->lineEdit->text();// 将框中的内容加入到ListWidgetui->listWidget->addItem(s);
}void Widget::on_pushButton_erase_clicked()
{// 获取ListWidget中选中的行int row=ui->listWidget->currentRow();if(row<0){return;}// 将框中的内容到ListWidget 删除ui->listWidget->takeItem(row);
}
- 执⾏程序, 观察效果. 可以新增元素, 选中元素, 删除元素
1.2 QTableWidget
使用 QTablewidget 表示一个表格控件,一个表格中包含若干行,每一行又包含若干列.表格中的每个单元格,是一个 QTablewidgetItem 对象
QTablewidget 核心方法
| 方法 | 说明 |
|---|---|
| item(int row, int column) | 根据行数列数获取指定的 OTablewidgetItem* |
| setltem(int row, int column,QTablewidget*) | 根据行数列数设置表格中的元素 |
| currentltem() | 返回被选中的元素 QTableWidgetltem |
| currentRow() | 返回被选中元素是第几行 |
| currentColumn() | 返回被选中元素是第几列 |
| row(QTableWidgetltem* ) | 获取指定 item 是第几行 |
| column(QTableWidgetltem* ) | 获取指定 item 是第几列 |
| rowCount() | 获取行数 |
| columnCount() | 获取列数 |
| insertRow(int row) | 在第 row 行处插入新行 |
| insertColumn(int column) | 在第 column 列插入新列 |
| removeRow(int row) | 删除第 row 行 |
| removeColumn(int column) | 删除第 column列 |
| setHorizontalHeaderltem(intcolumn, QTableWidget*) | 设置指定列的表头 |
| setVerticalHeaderltem(int row,QTableWidget*) | 设置指定行的表头 |
核心信号OTableWidgetItem
| 信号 | 说明 |
|---|---|
| cellClicked(int row, int column) | 点击单元格时触发 |
| cellDoubleClicked(int row, intcolumn) | 双击单元格时触发 |
| cellEntered(int row, int column) | 鼠标进入单元格时触发 |
| currentCellChanged(int row, intcolumn, int previousRow, intpreviousColumn) | 选中不同单元格时触发 |
QTableWidgetItem 核心方法
| 方法 | 说明 |
|---|---|
| row() | 获取当前是第几行 |
| column() | 获取当前是第几列 |
| setText(const QString&) | 设置文本 |
| setTextAlignment(int) | 设置文本对齐 |
| setlcon(const Qlcon&) | 设置图标 |
| setSelected(bool) | 设置被选中 |
| setSizeHints(const OSize&) | 设置尺寸 |
| setFont(const QFont&) | 设置字体 |
代码示例:使用 QTablewidget:用按钮新增和删除行和列
- 在界面上创建 QTablewidget 和 三个按钮,一个输入框
注意:QTablewidget 是 QTableView 的子类,功能比 QTableView 更丰富.咱们使用QTablewidget 即可
- 编写 widget.cpp 构造函数,构造表格中的初始数据
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 新增3行ui->tableWidget->insertRow(0);ui->tableWidget->insertRow(1);ui->tableWidget->insertRow(2);// 新增3列ui->tableWidget->insertColumn(0);ui->tableWidget->insertColumn(1);ui->tableWidget->insertColumn(2);// 设置水平的表头ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("学号"));ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("姓名"));ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("班级"));// 表格中加入数据ui->tableWidget->setItem(0,0,new QTableWidgetItem("1001"));ui->tableWidget->setItem(0,1,new QTableWidgetItem("张三"));ui->tableWidget->setItem(0,2,new QTableWidgetItem("20"));ui->tableWidget->setItem(1,0,new QTableWidgetItem("1002"));ui->tableWidget->setItem(1,1,new QTableWidgetItem("李四"));ui->tableWidget->setItem(1,2,new QTableWidgetItem("30"));ui->tableWidget->setItem(2,0,new QTableWidgetItem("1003"));ui->tableWidget->setItem(2,1,new QTableWidgetItem("王五"));ui->tableWidget->setItem(2,2,new QTableWidgetItem("40"));}
- 编写按钮的 slot 函数
void Widget::on_pushButton_addRow_clicked()
{// 获得当前表格的总行数int curRow=ui->tableWidget->rowCount();// 在最后一行新增// 新增的是下标是这一行ui->tableWidget->insertRow(curRow);
}void Widget::on_pushButton_subrow_clicked()
{// 获得当前选中的行int curRow=ui->tableWidget->currentRow();// 删除此行ui->tableWidget->removeRow(curRow);
}void Widget::on_pushButton_addcol_clicked()
{// 获得当前表格的总列数int curCol=ui->tableWidget->columnCount();// 在最后一列新增// 新增的是下标是这一列ui->tableWidget->insertColumn(curCol);// 给这一列设置列名const QString &s=ui->lineEdit->text();ui->tableWidget->setHorizontalHeaderItem(curCol,new QTableWidgetItem(s));}void Widget::on_pushButton_subcol_clicked()
{// 获得当前选中的列int curCol=ui->tableWidget->currentColumn();// 删除此列ui->tableWidget->removeColumn(curCol);
}
- 执⾏程序, 即可完成表格的基本操作
默认情况下,单元格中的内容直接就是可编辑的如果不想让用户编辑,可以设置 ui->tablewidget-setEditTriggers(QAbstractItemView::NoEditTriggers);
1.3 QTreeWidget
使用 QTreewidget 表示一个树形控件,里面的每个元素,都是一个 QTreewidgetItem,每个QTreewidgetItem 可以包含多个文本和图标,每个文本/图标为一个 列.可以给 QTreewidget 设置顶层节点(顶层节点可以有多个),然后再给顶层节点添加子节点,从而构成树形结构.
QTreewidget 核心方法
| 方法 | 说明 |
|---|---|
| clear | 清空所有子节点 |
| addTopLevelltem(QTreeWidgetltem* item) | 新增顶层节点 |
| topLevelltem(int index) | 获取指定下标的顶层节点 |
| topLevelltemCount() | 获取顶层节点个数 |
| indexOfTopLevelltem(QTreeWidgetltem* item) | 查询指定节点是顶层节点中的下标 |
| takeTopLevelltem(int index) | 删除指定的顶层节点.返回 QTreeWidgetltem*表示被删除的元素 |
| currentltem() | 获取到当前选中的节点,返回 QTreeWidgetltem |
| setCurrentltem(OTreeWidgetltem*item) | 选中指定节点 |
| setExpanded(bool) | 展开/关闭节点 |
| setHeaderLabel(const QString& text) | 设置 TreeWidget 的 header 名称. |
QTreeWidget 核心信号
| 信号 | 说明 |
|---|---|
| currentltemChanged(QTreeWidgetltemcurrent, QTreeWidgetltem old) | 切换选中元素时触发 |
| itemClicked(QTreeWidgetltem* item, int col) | 点击元素时触发 |
| itemDoubleClicked(QTreeWidgetltem* item,int col) | 双击元素时触发 |
| itemEntered(QTreeWidgetltem* item, int col) | 鼠标进入时触发 |
| itemExpanded(QTreeWidgetltem* item) | 元素被展开时触发 |
| itemCollapsend(QTreeWidgetltem*item) | 元素被折叠时触发 |
QTreeWidgetItem 核心属性
| 属性 | 说明 |
|---|---|
| text | 持有的文本 |
| textAlignment | 文本对齐方式 |
| icon | 持有的图表 |
| font | 文本字体 |
| hidden | 是否隐藏 |
| disabled | 是否禁用 |
| expand | 是否展开 |
| sizeHint | 尺寸大小 |
| selected | 是否选中 |
QTreeWidgetItem 核心方法
| 方法 | 说明 |
|---|---|
| addChild(QTreeWidgetltem* child) | 新增子节点 |
| childCount() | 子节点的个数 |
| child(int index) | 获取指定下标的子节点.返回 QTreeWidgetltem* |
| takeChild(int index) | 删除对应下标的子节点 |
| removeChild(QTreeWidgetltem*child) | 删除对应的子节点 |
| parent() | 获取该元素的父节点 |
代码示例: 使用 QTreewidget:
- 在界面上创建一个 TreeView,右键=>变形为=>TreeWidget,再创建一个lineEdit 和 两个按纽
注意:TreeWidget是 TreeView 的子类,功能比 TreeView 更丰富,咱们使用 TreeWidget即可
- 编写代码, 构造初始数据
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 新增顶层节点QTreeWidgetItem *item1=new QTreeWidgetItem();// 每一个节点都可以设置多列,在此就只设置一列item1->setText(0,"猫");// 将节点添加到顶层节点上ui->treeWidget->addTopLevelItem(item1);QTreeWidgetItem *item2=new QTreeWidgetItem();// 每一个节点都可以设置多列,在此就只设置一列item2->setText(0,"狗");// 将节点添加到顶层节点上ui->treeWidget->addTopLevelItem(item2);QTreeWidgetItem *item3=new QTreeWidgetItem();// 每一个节点都可以设置多列,在此就只设置一列item3->setText(0,"鸟");// 将节点添加到顶层节点上ui->treeWidget->addTopLevelItem(item3);// 添加一些子节点QTreeWidgetItem *item4=new QTreeWidgetItem();item4->setText(0,"中华田园猫");item1->addChild(item4);QTreeWidgetItem *item5=new QTreeWidgetItem();item5->setText(0,"布偶猫");item1->addChild(item5);QTreeWidgetItem *item6=new QTreeWidgetItem();item6->setText(0,"旋螺猫");item1->addChild(item6);
}
- 编写代码, 实现按钮的 slot 函数
void Widget::on_pushButton_clicked()
{// 先获取文本框中的内容QString s=ui->lineEdit->text();// 构造节点对象QTreeWidgetItem *item=new QTreeWidgetItem();item->setText(0,s);// 节点添加到相应的顶层节点中ui->treeWidget->addTopLevelItem(item);
}void Widget::on_pushButton_additem_clicked()
{// 先获取文本框中的内容QString s=ui->lineEdit->text();// 构造节点对象QTreeWidgetItem *item=new QTreeWidgetItem();item->setText(0,s);// 获取选中的元素QTreeWidgetItem *im=ui->treeWidget->currentItem();im->addChild(item);}void Widget::on_pushButton_subitem_clicked()
{// 先获取选中的节点QTreeWidgetItem *item=ui->treeWidget->currentItem();if(item==nullptr){return;}// 删除该节点,要获取此节点的父亲节点QTreeWidgetItem *parent= item->parent();if(parent==nullptr){// 顶层节点// 获取顶层节点的下标int index=ui->treeWidget->indexOfTopLevelItem(item);ui->treeWidget->takeTopLevelItem(index);}else{// 不是顶层节点parent->removeChild(item);}}
- 执⾏程序, 可以针对树形框进⾏编辑.

2. 容器类控件
2.1 QGroupBox
使用 QGroupBox 实现一个带有标题的分组框,可以把其他的控件放到里面作为一组,这样看起来能更好看一点.
注意,不要把 QGroupBox 和 QButtonGroup 混淆,(之前在介绍 QRadionButton 的时候提
到了QButtonGroup ).
核心属性
| 属性 | 说明 |
|---|---|
| title | 分组框的标题 |
| alignment | 分组框内部内容的对齐方式 |
| flat | 是否是"扁平"模式 |
| checkable | 是否可选择. 设为 true,则在 title 前方会多出一个可勾选的部分, |
| checked | 描述分组框的选择状态(前提是 checkable 为 true) |

2.2 QTabWidget
使用 QTabwidget 实现一个带有标签页的控件,可以往里面添加一些 widget.进一步的就可以通过标签页来切换.
核心属性
| 属性 | 说明 |
|---|---|
| tabPosition | 标签页所在的位置
|
| currentindex | 当前选中了第几个标签页(从0开始计算) |
| currentTabText | 当前选中的标签页的文本 |
| currentTabName | 当前选中的标签页的名字 |
| currentTablcon | 当前选中的标签页的图标 |
| currentTabToolTip | 当前选中的标签页的提示信息 |
| tabsCloseable | 标签页是否可以关闭 |
| movable | 标签页是否可以移动 |
核心信号
| 属性 | 说明 |
|---|---|
| currentChanged(int) | 在标签页发生切换时触发,参数为被点击的选项卡编号, |
| tabBarClicked(int) | 在点击选项卡的标签条的时候触发.参数为被点击的选项卡编号 |
| tabBarDoubleClicked(int) | 在双击选项卡的标签条的时候触发,参数为被点击的选项卡编号 |
| tabCloseRequest(int) | 在标签页关闭时触发.参数为被关闭的选项卡编号 |
代码示例:使用标签页管理多组控件,按钮新增标签页,删除标签页
- 在界面上创建一个 QTabwidget,和两个按钮按钮的 objectName 为pushButton_add 和 pushButton_remove
- 编写 widget.cpp,进行初始化,给标签页中放个简单的 label
注意新创建的 label的父元素,是 ui->tab 和 ui->tab 2 .Qt中使用父子关系决定该控件"在哪里”
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建2个按钮来实现新增标签页,删除标签页// 在每一个标签页中添加标签QLabel *label1=new QLabel(ui->tab);label1->setText("这是标签页1");label1->resize(100,50);QLabel *label2=new QLabel(ui->tab_2);label2->setText("这是标签页2");label2->resize(100,50);}
- 编写按钮的 slot 函数
- 获取到标签页的个数.使用count()
- 使⽤ addTab 新增标签⻚.
- 使⽤ removeTab 删除标签⻚.
- 使⽤ currentIndex 获取到当前标签⻚的下标.
- 使⽤ setCurrentIndex 切换当前标签⻚
void Widget::on_pushButton_clicked()
{// 获取现存标签页的总数int count=ui->tabWidget->count();// 新增标签页// 创建一个标签页对象QWidget *t=new QWidget();ui->tabWidget->addTab(t,QString("Tab") + QString::number(count+1));// 在新增的标签页中加入标签QLabel *label = new QLabel(t);label->setText(QString("这是标签页")+ QString::number(count+1));// 新增的标签页要自动打开被选中,将新增的标签页进行设置为选中ui->tabWidget->setCurrentWidget(t);
}void Widget::on_pushButton_2_clicked()
{// 获取选中的标签页int index=ui->tabWidget->currentIndex();// 进行删除ui->tabWidget->removeTab(index);
}
- 运行程序,观察效果
点击新建标签页,可以创建出新的标签
点击删除当前标签页,可以删除标签
3. 布局管理器
之前使用 Qt 在界面上创建的控件,都是通过"绝对定位"的方式来设定的,也就是每个控件所在的位置,都需要计算坐标,最终通过 setGeometry 或者 move 方式摆放过去.
这种设定方式其实并不方便,尤其是界面如果内容比较多,不好计算,而且一个窗口大小往往是可以调整的,按照绝对定位的方式,也无法自适应窗口大小,因此 Qt引入"布局管理器"(Layout)机制,来解决上述问题,
3.1 QVBoxLayout(垂直布局)
使用 QVBoxLayout 表示垂直的布局管理器
核心属性
| 属性 | 说明 |
|---|---|
| layoutLeftMargin | 左侧边距 |
| layoutRightMargin | 右侧边距 |
| layoutTopMargin | 上方边距 |
| layoutBottomMargin | 下方边距 |
| layoutSpacing | 相邻元素之间的间距 |
Layout 只是⽤于界⾯布局, 并没有提供信号
代码示例: 创建两个 QVBoxLayout
- 在界面上创建两个 QVBoxLayout,每个 QVBoxLayout 各放三个按钮
- 运行程序,可以看到这些按钮已经自动排列好,只不过当前这些按钮的位置不能随着窗口大小自动变化
3.2 QHBoxLayout(水平布局)
使用 QHBoxLayout 表示垂直的布局管理器.
核心属性(和 QVBoxLayout 属性是一致的)
| 属性 | 说明 |
|---|---|
| layoutLeftMargin | 左侧边距 |
| layoutRightMargin | 右侧边距 |
| layoutTopMargin | 上方边距 |
| layoutBottomMargin | 下方边距 |
| layoutSpacing | 相邻元素之间的间距 |
代码示例: 嵌套的layout
- 在代码中创建以下内容
使用 addLayout 给layout 中添加子layout,
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建一个垂直布局管理器QVBoxLayout *cayout=new QVBoxLayout();// 创建两个按钮QPushButton*button1=new QPushButton("按钮1");QPushButton*button2=new QPushButton("按钮2");// 将按钮设置到垂直管理器中cayout->addWidget(button1);cayout->addWidget(button2);// 创建一个水平管理器中QHBoxLayout *hayout=new QHBoxLayout();QPushButton*button3=new QPushButton("按钮3");QPushButton*button4=new QPushButton("按钮4");// 将按钮设置到水平管理器中hayout->addWidget(button3);hayout->addWidget(button4);// 水平管理器添加到垂直管理器cayout->addLayout(hayout);// 垂直管理器设置到窗口中this->setLayout(cayout);
}
- 执⾏程序,观察结果
3.3 QGridLayout
Qt中还提供了 QGridLayout 用来实现网格布局的效果,可以达到 M*N的这种网格的效果.
核⼼属性
| 属性 | 说明 |
|---|---|
| layoutLeftMargin | 左侧边距 |
| layoutRightMargin | 右侧边距 |
| layoutTopMargin | 上方边距 |
| layoutBottomMargin | 下方边距 |
| layoutHorizontalSpacing | 相邻元素之间水平方向的间距 |
| layoutVerticalSpacing | 相邻元素之间垂直方向的间距 |
| layoutRowStretch | 行方向的拉伸系数 |
| layoutColumnStretch | 列方向的拉伸系数 |
代码示例: 使用 QGridLayout 管理元素
- 代码中创建 QGridLayout 和4个按钮,
使用 addwidget 添加控件到布局管理器中,但是添加的同时会指定两个坐标,表示放在第几行,第几列.
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 4 个按钮QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");QPushButton* btn4 = new QPushButton("按钮4");// 创建⽹格布局管理器, 并且添加元素QGridLayout* layout = new QGridLayout();layout->addWidget(btn1, 0, 0);layout->addWidget(btn2, 0, 1);layout->addWidget(btn3, 1, 0);layout->addWidget(btn4, 1, 1);// 设置 layout 到窗⼝中.this->setLayout(layout);
}
- 执行代码,观察效果.可以看到当前的这几个按钮是按照2行2列的方式排列的,
- 如果调整⾏列坐标为下列代码
// 创建⽹格布局管理器, 并且添加元素
QGridLayout* layout = new QGridLayout();
layout->addWidget(btn1, 0, 0);
layout->addWidget(btn2, 0, 1);
layout->addWidget(btn3, 0, 2);
layout->addWidget(btn4, 0, 3);
执⾏代码, 可以看到这⼏个按钮都在同⼀⾏了. 相当于 QHBoxLayout
4) 如果调整⾏列坐标为下列代码
QGridLayout* layout = new QGridLayout();
layout->addWidget(btn1, 1, 0);
layout->addWidget(btn2, 2, 0);
layout->addWidget(btn3, 3, 0);
layout->addWidget(btn4, 4, 0);
3.4 QFormLayout
除了上述的布局管理器之外,Qt还提供了 QFormLayout,属于是 QGridLayout 的特殊情况,专门用于实现两列表单的布局.
这种表单布局多用于让用户填写信息的场景,左侧列为提示,右侧列为输入框.
代码示例:使用 QFormLayout 创建表单
- 编写代码,创建 QFormLayout,以及三个label和三个 lineEdit
- 使用 addRow 方法来添加一行,每行包含两个控件,第一个控件固定是 QLabel/文本,第二个控件则可以是任意控件
- 如果把第一个参数填写为 NULL,则什么都不显示,
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 设置成 3 行 2列的表单QFormLayout *layout=new QFormLayout();this->setLayout(layout);QLabel *label1=new QLabel("标签1");QLabel *label2=new QLabel("标签1");QLabel *label3=new QLabel("标签1");QLineEdit *edit1=new QLineEdit();QLineEdit *edit2=new QLineEdit();QLineEdit *edit3=new QLineEdit();// 上述控件添加到表单布局中layout->addRow(label1,edit1);layout->addRow(label2,edit2);layout->addRow(label3,edit3);QPushButton *button=new QPushButton("提交");layout->addRow(button);}
- 执⾏程序, 可以看到以下结果
3.5 QSpacerItem
使用布局管理器的时候,可能需要在控件之间,添加一段空白.就可以使用 QSpacerItem 来表示.
核心属性
| 属性 | 说明 |
|---|---|
| width | 宽度 |
| height | 高度 |
| hData | 水平方向的 sizePolicy
|
| vData | 垂直方向的 sizePolicy 选项同上. |
代码示例: 创建一组左右排列的按钮
- 在界面上创建一个 QVBoxLayout,并添加两个按钮
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QHBoxLayout* layout = new QHBoxLayout();this->setLayout(layout);QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");layout->addWidget(btn1);layout->addWidget(btn2);
}
- 直接运行程序,可以看到两个按钮是紧挨着的
- 在两个按钮中间添加⼀个 spacer
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QHBoxLayout* layout = new QHBoxLayout();this->setLayout(layout);QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");// 创建 SpacerQSpacerItem* spacer = new QSpacerItem(200, 20);layout->addWidget(btn1);// 在两个 widget 中间添加空⽩layout->addSpacerItem(spacer);layout->addWidget(btn2);
}
- 运行程序,观察代码效果,可以看到两个按钮之间已经存在了间隔了调整 QSpacerltem 不同的尺寸,即可看到不同的间距
相关文章:
Qt-常用控件(3)-多元素控件、容器类控件和布局管理器
1. 多元素控件 Qt 中提供的多元素控件有: QListWidgetQListViewQTableWidgetQTableViewQTreeWidgetQTreeView xxWidget 和 xxView 之间的区别,以 QTableWidget 和 QTableView 为例. QTableView 是基于 MVC 设计的控件.QTableView 自身不持有数据,使用 QTableView 的…...
【系统设计】主动查询与主动推送:如何选择合适的数据传输策略
基本描述总结 主动查询机制:系统A主动向系统B请求数据,采用严格的权限控制和身份认证,防止未授权的数据访问。数据在传输过程中使用TLS加密,并通过动态脱敏处理隐藏敏感信息。 推送机制:系统B在数据更新时主动向系统…...
mac 安装brew并配置国内源
前置条件 - Xcode 命令行工具 一行代码安装Homebrew 添加到路径(PATH) - zsh shell为例 背景介绍 最近重装了我的MAC mini (m1 芯片), 很多软件都需要重新安装,因为后续还需要安装一些软件,所以想着安装个包管理软件 什么…...
Temu官方宣导务必将所有的点位材料进行检测-RSL资质检测
关于饰品类产品合规问题宣导: 产品法规RSL要求 RSL测试是根据REACH法规及附录17的要求进行测试。REACH法规是欧洲一项重要的法规,其中包含许多对化学物质进行限制的规定和高度关注物质。 为了确保珠宝首饰的安全性,欧盟REACH法规规定&#…...
mysql高级sql
文章目录 一,查询1.按关键字排序1.1按关键字排序操作(1)按分数排序查询(不加asc默认为升序)(2)按分数降序查询(DESC)(3)使用where进行条件查询(4)使用ORDER BY语句对多个字段排序 1.2使用区间判断查询(and/…...
Linux CentOS 7.9 安装mysql8
1、新建mysql文件夹 数据比较大,所以我在服务器另外挂了一个盘装mysql,和默认安装一个道理,换路径即可 cd ../ //创建文件夹 mkdir mysql //进入mysql文件夹 cd mysql 2、下载mysql8.0安装包并解压、重命名 //下载安装包 wget https://dev…...
替代 Django 默认 User 模型并使用 `django-mysql` 添加数据库备注20240904
替代 Django 默认 User 模型并使用 django-mysql 添加数据库备注 前言 在 Django 项目开发中,默认的 User 模型虽然能够满足许多基础需求,但在实际项目中我们常常需要对用户模型进行定制化。通过覆盖默认的 User 模型,我们可以根据具体的业…...
三维激光扫描点云配准外业棋盘的布设与棋盘坐标测量
文章目录 一、棋盘标定板准备二、棋盘标定板布设三、棋盘标定板坐标测量一、棋盘标定板准备 三维激光扫描棋盘是用来校准和校正激光扫描仪的重要工具,主要用于提高扫描精度。棋盘标定板通常具有以下特点: 高对比度图案:通常是黑白相间的棋盘格,便于识别。已知尺寸:每个格…...
【Python知识宝库】文件操作:读写文件的最佳实践
🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、文件读取1. 使用open函数2. 逐行读取3. 使用readlines和readline 二、文件写入1. 写入文本2. 追加内容3. 写入…...
Chapter 13 普通组件的注册使用
欢迎大家订阅【Vue2Vue3】入门到实践 专栏,开启你的 Vue 学习之旅! 文章目录 前言一、组件创建二、局部注册三、全局注册 前言 在 Vue.js 中,组件是构建应用程序的基本单元。本章详细讲解了注册和使用 Vue 的普通组件的两种方式:…...
u盘显示需要格式化才能用预警下的数据拯救恢复指南
U盘困境:需要格式化的紧急应对 在数字信息爆炸的时代,U盘作为便携的数据存储介质,承载着我们工作、学习乃至生活中的大量重要资料。然而,当U盘突然弹出“需要格式化才能用”的提示时,这份便捷瞬间转化为焦虑与不安。这…...
还不懂BIO,NIO,AIO吗
BIO(Blocking I/O)、NIO(Non-blocking I/O)和 AIO(Asynchronous I/O)是 Java 中三种不同的 I/O 模型,主要用于处理输入 / 输出操作。 一、BIO(Blocking I/O) 定义与工作原…...
物联网——DMA+AD多通道
DMA简介 存储器映像 某些数据在运行时不会发生变化,则设置为常量,存在Flash存储器中,节省运行内存的空间 DMA结构图 DMA访问权限高于cpu 结构要素 软件触发源:存储器到存储器传输完成后,计数器清零 硬件触发源&…...
Vue 中 watch 和 watchEffect 的区别
watch 和 watcheffect 都是 vue 中用于监视响应式数据的 api,它们的区别在于:watch 用于监视特定响应式属性并执行回调函数。watcheffect 用于更通用的响应式数据监视,但回调函数中不能更新响应式数据。Vue 中 watch 和 watchEffect 的区别 …...
pip install pyaudio sounddevice error: externally-managed-environment
shgbitaishgbitai-C9X299-PGF:~/pythonworkspace/ai-accompany$ pip install pyaudio sounddevice error: externally-managed-environment This environment is externally managed ╰─> To install Python packages system-wide, try apt installpython3-xyz, where xyz …...
HTML 转 PDF API 接口
HTML 转 PDF API 接口 网络工具 / 文件处理 支持网页转 PDF 高效生成 PDF / 提供永久链接。 1. 产品功能 超高性能转换效率;支持将传递的 HTML 转换为 PDF,支持转换 HTML 中的 CSS 格式;支持传递网站 URL,直接转换页面成对应的 …...
http://localhost:15672/ 无法访问
注意erlang版本和rabbitmq的版本要保持兼容 rabbitmq和erlang对应关系如下:https://www.rabbitmq.com/which-erlang.html 目前我选择的erlang版本是:otp_win64_24.3.3,rabbit版本是:rabbitmq-server-3.10.18.exe 如果两者之间的版…...
6.3图的遍历
图的遍历是指从某点出发,按照某种搜索方式沿着边访问图中所有节点 图的遍历算法主要有两种:广度优先,深度优先 都需要辅助数组visited[]来记录节点是否被访问过 6.3.1广度优先搜索 like层次遍历,需要辅助队列 代码实现 #include<stdio.h> #define maxnum 15 bool vi…...
2024数学建模国赛选题建议+团队助攻资料(已更新完毕)
目录 一、题目特点和选题建议 二、模型选择 1、评价模型 2、预测模型 3、分类模型 4、优化模型 5、统计分析模型 三、white学长团队助攻资料 1、助攻代码 2、成品论文PDF版 3、成品论文word版 9月5日晚18:00就要公布题目了,根据历年竞赛题目…...
大学课程-人机交互期末复习
绪论 什么是人机交互技术?⭐⭐ 是指关于设计、评价和实现供人们使用的交互式计算机系统,并围绕相关的主要现象进行研究的学。狭 义的讲,人机交互技术主要是研究人与计算机之间的信息交换,它主要包括人到计算机和计算机到人的 信息…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
STM32标准库-ADC数模转换器
文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”:输入模块(GPIO、温度、V_REFINT)1.4.2 信号 “调度站”:多路开关1.4.3 信号 “加工厂”:ADC 转换器(规则组 注入…...














