Qt常用控件(五) - 多元素控件

一、多元素控件

Qt中提供的多元素控件有:QListWidget、QListView、QTableWidget、QTableView、QTreeWidget和QTreeView

XXWidget和XXView的区别

以 QTableWidget 和 QTableView 为例

  • QTableView 是采用 MVC 设计模式的控件,其本身并不存储数据。使用时需要用户创建一个 Model 对象(例如 QStandardModel),并将该 Model 与 QTableView 进行关联。这种关联实现了双向绑定:修改 Model 中的数据会同步更新 QTableView 的显示内容,反之,通过 QTableView 修改显示内容也会自动更新 Model 中的数据。
  • QTableWidget 是 QTableView 的子类,它封装了 Model 功能。用户无需手动创建 Model 对象,可以直接向 QTableWidget 中添加数据。

二、QListWidget

使用 QListWidget 能够显示⼀个纵向的列表,每个选项都可以被选中

属性 说明
currentRow 当前被选中的是第几行
count 一共有多少行
sortingEnabled 是否允许排序
isWrapping 是否运行换行
itemAlignment 元素的对齐方式
selectRectVisible 被选中的元素矩形是否可见
spacing 元素之间的间隔

核心方法

方法 说明
addItem(const QString& label)、addItem(QListWidgetItem *item) 列表中添加元素
currentItem() 返回 QListWidgetItem* 表示当前选中的元素
setCurrentItem(QListWidgetItem* item) 设置选中哪个元素
setCurrentRow(int row) 设置选中第几行的元素
insertItem(const QString& label, int row) 、insertItem(QListWidgetItem *item, introw) 在指定的位置插入元素
item(int row) 返回 QListWidgetItem* 表示第 row 行的元素
takeItem(int row) 删除指定行的元素, 返回 QListWidgetItem* 表示是哪个元素被删除了

核心信号

信号 说明
currentItemChanged(QListWidgetItem* current, QListWidgetItem* old) 选中不同元素时会触发, 参数是当前选中的元素和之前选中的元素
currentRowChanged(int) 选中不同元素时会触发, 参数是当前选中元素的行数
itemClicked(QListWidgetItem* item) 点击某个元素时触发
itemDoubleClicked(QListWidgetItem* item) 双击某个元素时触发
itemEntered(QListWidgetItem* item) 鼠标进入元素时触发

上面我们涉及到了一个关键的类QListWidgetItem,这个类表示QListWidget中的一个元素,本质上就是"文本+图标"构成的

方法 说明
setFont 设置字体
setIcon 设置图标
setHidden 设置隐藏
setSizeHint 设置尺寸
setSelected 设置是否被选中
setText 设置文本
setTextAlignment 设置文本对齐方式

代码样例(使用ListWidget):

首先,在界面上创建⼀个 ListView , 右键 => 变形为 => ListWidget , 再创建⼀个 lineEdit 和 两个按钮

编写widget.cpp,初始化构造函数

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("C");
}

编写listWidget的槽函数,需要注意,两个指针初识情况下是没有选中的,就会导致两个指针指向的是NULL

cpp 复制代码
void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
    if(current != NULL && previous != NULL)
    {
        qDebug() << "当前被选中: " << current->text() << " 之前选择: " << previous->text();
    }
}

上述代码主要要包含头文件

编写按钮的槽函数

cpp 复制代码
void Widget::on_pushButton_add_clicked()
{
    //获取输入框中的数据
    const QString& text = ui->lineEdit->text();
    if(text.isEmpty())
    {
        return;
    }
    ui->listWidget->addItem(text);
}

void Widget::on_pushButton_sub_clicked()
{
    //获取当前被选中的元素
    int row = ui->listWidget->currentRow();
    //删除这一行
    ui->listWidget->takeItem(row);
}

运行代码:

三、QTableWidget

QTableWidget 用于显示表格控件。该表格由多行组成,每行包含若干列。每个单元格对应一个 QTableWidgetItem 对象。

核心方法

方法 说明
item(int row, int column) 根据行数列数获取指定的 QTableWidgetItem*
setItem(int row, int column,QTableWidget*) 根据行数列数设置表格中的元素
currentItem() 返回被选中的元素 QTableWidgetItem*
currentRow() 返回被选中元素是第几行
currentColumn() 返回被选中元素是第几列
row(QTableWidgetItem* ) 获取指定 item 是第几行
column(QTableWidgetItem* ) 获取指定 item 是第几列
rowCount() 获取行数
columnCount() 获取列数
insertRow(int row) 在第 row 行处插入新行
insertColumn(int column) 在第 column 列插入新列
removeRow(int row) 删除第 row 行
removeColumn(int column) 删除第 column 列
setHorizontalHeaderItem(int column, QTableWidget*) 设置指定列的表头
setVerticalHeaderItem(int row,QTableWidget*) 设置指定行的表头

QTableWidgetItem 核心信号

信号 说明
cellClicked(int row, int column) 点击单元格时触发
cellDoubleClicked(int row, int column) 双击单元格时触发
cellEntered(int row, int column) 鼠标进入单元格时触发
currentCellChanged(int row, int column, int previousRow, int previousColumn) 选中不同单元格时触发

QTableWidgetItem 核心方法

方法 说明
row() 获取当前是第几行
column() 获取当前是第几列
setText(const QString&) 设置文本
setTextAlignment(int) 设置文本对齐
setIcon(const QIcon&) 设置图标
setSelected(bool) 设置被选中
setSizeHints(const QSize&) 设置尺寸
setFont(const QFont&) 设置字体

代码样例(使用QTableWidget):

首先,在界面上创建一个QTableWidget和四个按钮,一个输入框。

编写widget.cpp

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);

    //给3列设定列名
    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("18"));

    ui->tableWidget->setItem(1, 0, new QTableWidgetItem("1002"));
    ui->tableWidget->setItem(1, 1, new QTableWidgetItem("李四"));
    ui->tableWidget->setItem(1, 2, new QTableWidgetItem("20"));

    ui->tableWidget->setItem(2, 0, new QTableWidgetItem("1003"));
    ui->tableWidget->setItem(2, 1, new QTableWidgetItem("王五"));
    ui->tableWidget->setItem(2, 2, new QTableWidgetItem("19"));

    //如果不想要用户编辑单元格
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
}

设置槽函数

cpp 复制代码
void Widget::on_pushButton_add_row_clicked()
{
    //获取行数
    int rowCount = ui->tableWidget->rowCount();
    ui->tableWidget->insertRow(rowCount);
}

void Widget::on_pushButton_delete_row_clicked()
{
    //获取选中的行号
    int row = ui->tableWidget->currentRow();
    ui->tableWidget->removeRow(row);
}

void Widget::on_pushButton_add_col_clicked()
{
    //获取列数
    int colCount = ui->tableWidget->columnCount();
    ui->tableWidget->insertColumn(colCount);
    //从文本中获取列名
    const QString& name = ui->lineEdit->text();
    ui->tableWidget->setHorizontalHeaderItem(colCount, new QTableWidgetItem(name));
}

void Widget::on_pushButton_delete_col_clicked()
{
    int col = ui->tableWidget->currentColumn();
    ui->tableWidget->removeColumn(colorCount());
}

运行代码:

四、QTreeWidget

使用 QTreeWidget 可以创建树形控件。每个元素都是 QTreeWidgetItem 对象,这些对象可以包含多列文本和图标数据。

QTreeWidget 支持设置多个顶层节点,通过向顶层节点添加子节点,即可构建完整的树形层级结构。

核心方法

方法 说明
clear 清空所有子节点
addTopLevelItem(QTreeWidgetItem* item) 新增顶层节点
topLevelItem(int index) 获取指定下标的顶层节点
topLevelItemCount() 获取顶层节点数
indexOfTopLevelItem(QTreeWidgetItem* item) 查询指定节点是顶层节点中的下标
takeTopLevelItem(int index) 删除指定的顶层节点. 返回 QTreeWidgetItem* 表示被删除的元素
currentItem() 获取到当前选中的节点, 返回 QTreeWidgetItem*
setCurrentItem(QTreeWidgetItem* item) 选中指定节点
setExpanded(bool) 展开/关闭节点
setHeaderLabel(const QString& text) 设置 TreeWidget 的 header 名称

QTreeWidget 核心信号

信号 说明
currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* old) 切换选中元素时触发
itemClicked(QTreeWidgetItem* item, int col) 点击元素时触发
itemDoubleClicked(QTreeWidgetItem* item,int col) 双击元素时触发
itemEntered(QTreeWidgetItem* item, int col) 鼠标进入时触发
itemExpanded(QTreeWidgetItem* item) 元素被展开时触发
itemCollapsend(QTreeWidgetItem* item) 元素被折叠时触发

QTreeWidgetItem 核心属性

属性 说明
text 持有的文本
textAlignment 文本对齐方式
icon 持有的图表
font 文本字体
hidden 是否有隐藏
disabled 是否禁用
expand 是否展开
sizeHint 尺寸大小
selected 是否选中

QTreeWidgetItem 核心方法

方法 说明
addChild(QTreeWidgetItem* child) 新增子节点
childCount() 子节点的个数
child(int index) 获取指定下标的子节点, 返回 QTreeWidgetItem*
takeChild(int index) 删除对应下标的子节点
removeChild(QTreeWidgetItem* child) 删除对应的子节点
parent() 获取该元素的父节点

代码样例(使用QTreeWidget):

首先,在界面上创建⼀个 TreeView , 右键 => 变形为 => TreeWidget , 再创建⼀个 lineEdit 和 三个按钮

编写widget.cpp文件

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置根节点标题
    ui->treeWidget->setHeaderLabel("动物");
    //新增顶层节点
    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);
}

编写槽函数

cpp 复制代码
void Widget::on_pushButton_addTopElement_clicked()
{
    //获取输入框内容
    const QString& text = ui->lineEdit->text();
    if(text.isEmpty())
    {
        return ;
    }
    //将获取的内容插入顶层节点
    QTreeWidgetItem* item = new QTreeWidgetItem();
    item->setText(0, text);
    ui->treeWidget->addTopLevelItem(item);
}

void Widget::on_pushButton_addSelectElement_clicked()
{
    //获取输入框内容
    const QString& text = ui->lineEdit->text();
    if(text.isEmpty())
    {
        return ;
    }
    //获取当前选中的节点
    QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();
    if(currentItem == NULL)
    {
        return;
    }
    //构造新的item
    QTreeWidgetItem* newItem = new QTreeWidgetItem();
    newItem->setText(0, text);
    //添加新的item到选中节点中
    currentItem->addChild(newItem);
    //展开父节点
    currentItem->setExpanded(true);
}

void Widget::on_pushButton_deleteElement_clicked()
{
    //获取当前选中节点
    QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();
    if(currentItem == NULL)
    {
        return ;
    }
    //获取当前节点的父节点
    QTreeWidgetItem* parent = currentItem->parent();
    if(parent == NULL)
    {
        //为顶层节点
        int index = ui->treeWidget->indexOfTopLevelItem(currentItem);
        ui->treeWidget->takeTopLevelItem(index);
    }
    else
    {
        //不是顶层节点
        parent->removeChild(currentItem);
    }
}

运行代码:

五、QGroupBox

使用 QGroupBox 创建带标题的分组框,可将相关控件归为一组显示,使界面布局更加美观清晰。

核心属性

属性 说明
title 分组框标题
alignment 分组框内部内容对齐方式
flat 是否是"扁平"模式
checkable 是否可选择:设为 true, 则在 title 前方会多出⼀个可勾选的部分
checked 描述分组框的选择状态 (前提是 checkable 为 true)

注意:分组框主要用于界面美化,不涉及用户交互和业务逻辑,属于锦上添花的组件。

代码样例(给麦当劳样例加上分组框):

首先,在界面上创建三个分组框, 并且在分组框内部创建下拉框和微调框

编写widget.cpp文件

cpp 复制代码
Widget::Widget(QWidget *parent)
 : QWidget(parent)
 , ui(new Ui::Widget)
{
 	ui->setupUi(this);
 	ui->comboBox->addItem("巨⽆霸");
 	ui->comboBox->addItem("⻨辣鸡腿堡");
 	ui->comboBox_2->addItem("薯条");
 	ui->comboBox_2->addItem("⻨辣鸡翅");
 	ui->comboBox_3->addItem("可乐");
 	ui->comboBox_3->addItem("雪碧");
}

运行程序:

六、QTabWidget

使用 QTabWidget 创建带标签页的控件,可向其中添加多个 widget,通过切换标签页来展示不同内容。

核心属性

属性 说明
tabPosition 标签页所在的位置: North 上方、South 下方、 West 左侧、East 右侧
currentIndex 当前选中了第几个标签页 (从 0 开始计算)
currentTabText 当前选中的标签页的文本
currentTabName 当前选中的标签页的名字
currentTabIcon 当前选中的标签页的图标
currentTabToolTip 当前选中的标签页的信息
tabsCloseable 标签页是否可以关闭
movable 标签页是否可以移动

核心信号

信号 说明
currentChanged(int) 在标签页发生切换时触发, 参数为被点击的选项卡编号
tabBarClicked(int) 在点击选项卡的标签条的时候触发. 参数为被点击的选项卡编号
tabBarDoubleClicked(int) 在双击选项卡的标签条的时候触发. 参数为被点击的选项卡编号
tabCloseRequest(int) 在标签页关闭时触发. 参数为被关闭的选项卡编号.

代码样例(使用标签页管理多组控件):

首先,在界面上创建⼀个 QTabWidget , 和两个按钮

注意:QTabWidget 中的每个标签页都是一个独立的 QWidget 组件:

  • 点击标签即可快速切换页面
  • 右键点击 QTabWidget 可进行添加或删除标签页操作

编写widget.cpp文件,注意新创建的 label 的父元素, 是 ui->tab 和 ui->tab_2 . Qt 中使用父子关系决定该控件 "在哪里".

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QLabel* label = new QLabel(ui->tab);
    label->setText("标签一");
    label->resize(100, 50);

    QLabel* label2 = new QLabel(ui->tab_2);
    label2->setText("标签二");
    label2->resize(100, 50);
}

编写槽函数

cpp 复制代码
void Widget::on_pushButton_add_clicked()
{
    //获取当前有几个标签
    int count = ui->tabWidget->count();
    //创建新的widget
    QWidget* w = new QWidget();
    ui->tabWidget->addTab(w, QString("Tab") + QString::number(count + 1));
    //给新添加的widget设置label
    QLabel* label = new QLabel(w);
    label->setText(QString("标签") + QString::number(count + 1));
    label->resize(100, 50);
    //选中新标签
    ui->tabWidget->setCurrentIndex(count);
}

void Widget::on_pushButton_del_clicked()
{
    //获取当前标签下标
    int index = ui->tabWidget->currentIndex();
    //删除这个标签
    ui->tabWidget->removeTab(index);
}

void Widget::on_tabWidget_currentChanged(int index)
{
    qDebug() << "当前选中标签⻚为: " << index;
}

运行代码:

如果不想按按钮删除可以勾选QTabWidget中的tabsClosable

相关推荐
熬了夜的程序员2 小时前
【Rust学习之路】序
开发语言·后端·学习·rust
say_fall2 小时前
C语言编程实战:每日一题:用栈实现队列
c语言·开发语言
deng-c-f2 小时前
C/C++内置库函数(4):c++左右值及引用的概念、move/forward的使用
c语言·开发语言·c++
零雲2 小时前
java面试:怎么保证消息队列当中的消息丢失、重复问题?
java·开发语言·面试
冬夜戏雪2 小时前
【java学习日记】【12.11】【11/60】
java·开发语言
在坚持一下我可没意见2 小时前
Spring 后端安全双剑(下篇):JWT 无状态认证 + 密码加盐加密实战
java·开发语言·spring boot·后端·安全·spring
deng-c-f3 小时前
C/C++内置库函数(3):future、promise的用法
c语言·开发语言·c++
2501_921649493 小时前
亚太股票数据API:日股、韩股、新加坡股票、印尼股票市场实时行情,实时数据API-python
开发语言·后端·python·websocket·金融
chaodaibing3 小时前
【Java】一个批量更新插入数据到MySQL的工具类
java·开发语言·mysql