【Qt常用控件】多元素控件

文章目录

  • [1. List Widget](#1. List Widget)
  • [2. Table Widget](#2. Table Widget)
  • [3. Tree Widget](#3. Tree Widget)

Qt 中提供的多元素控件有:

  • QListWidget
  • QListView
  • QTableWidget
  • QTableView
  • QTreeWidget
  • QTreeView

xxWidget 和 xxView 之间的区别 :

此处 xxView 是 MVC 结构的一种典型实现

MVC 也是软件开发中,非常经典的 软件结构的 组织形式了.

  • M:model 数据
  • V:view 视图 (界面)
  • C:controller 控制器数据和视图之间的业务流程

此处 xxView 只是负责实现了视图,不负责数据如何存储表示,更不负责数据和视图之间的交互。因此如果使用xxView 就需要程序员自己实现 model和 controller 的部分.就比较麻烦~~

xxWidget 基于xxView同时把 model 和 controller 都帮我们实现好了~ 拿过来就可以使用.人家提供了功能很方便的api,让我们直接就用~

以 QTableWidget 和 QTableView 为例.

  • QTableView 是基于 MVC 设计的控件. QTableView 自身不持有数据. 使用 QTableView 的时候需要用户创建一个 Model 对象 (比如 QStandardModel ), 并且把 Model 和 QTableView 关联起来. 后续修改 Model 中的数据就会影响 QTableView 的显示; 修改 QTableView 的显示也会影响到 Model 中的数据(双向绑定).
  • QTableWidget 则是 QTableView 的子类, 对 Model 进行了封装. 不需要用户手动创建 Model 对象, 直接就可以往 QTableWidget 中添加数据了

1. List Widget

使用 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, int row) 在指定的位置插入元素
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 或者直接创建一个 ListWidget, 再创建一个 lineEdit 和 两个按钮.

注意: ListWidget 是 ListView 的子类, 功能比 ListView 更丰富. 咱们使用 ListWidget 即可.

编写 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("Python");
}

编写 listWidget 的 slot 函数

  • 此处需要判定 current 和 previous 非空. 初始情况下是没有元素选中的, 就导致这俩指针可能是 NULL.
cpp 复制代码
void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
    if(current != nullptr)
    {
        qDebug() << "当前选中的元素: " << current->text();
    }
    if(previous != nullptr)
    {
        qDebug() << "上次选中的元素: " << previous->text();
    }
} 

注意:这里需要给 widget.h 前面加上 #include

编写按钮的 slot 函数

cpp 复制代码
void Widget::on_pushButton_insert_clicked()
{
    const QString& text = ui->lineEdit->text();
    if(text.isEmpty())
    {
        return;
    }
    ui->listWidget->addItem(text);
}

void Widget::on_pushButton_erase_clicked()
{
    int row = ui->listWidget->currentRow();
    if(row < 0)
    {
        return;
    }
    ui->listWidget->takeItem(row);
}

运行结果:


2. Table Widget

使用 QTableWidget 表示一个表格控件. 一个表格中包含若干行, 每一行又包含若干列.

表格中的每个单元格, 是一个 QTableWidgetItem 对象.

QTableWidget 核心方法

方法 说明
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 和 三个按钮, 一个输入框

注意: QTableWidget 是 QTableView 的子类, 功能比 QTableView 更丰富. 咱们使用 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);
    // 设置列名
    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("18"));
    ui->tableWidget->setItem(2, 0,  new QTableWidgetItem("1003"));
    ui->tableWidget->setItem(2, 1,  new QTableWidgetItem("王五"));
    ui->tableWidget->setItem(2, 2,  new QTableWidgetItem("22"));
}

编写按钮的 slot 函数

cpp 复制代码
void Widget::on_pushButton_insertRow_clicked()
{
    int rowCount = ui->tableWidget->rowCount();
    ui->tableWidget->insertRow(rowCount);
}

void Widget::on_pushButton_insertCol_clicked()
{
    int colCount = ui->tableWidget->columnCount();
    ui->tableWidget->insertColumn(colCount);
    // 设置列名
    const QString& text = ui->lineEdit->text();
    ui->tableWidget->setHorizontalHeaderItem(colCount, new QTableWidgetItem(text));
}

void Widget::on_pushButton_deleteRow_clicked()
{
    int row = ui->tableWidget->currentRow();
    ui->tableWidget->removeRow(row);
}

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

运行结果:

默认情况下, 单元格中的内容直接就是可编辑的.

如果不想让用户编辑, 可以设置

ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);


3. Tree Widget

使用 QTreeWidget 表示一个树形控件. 里面的每个元素, 都是一个 QTreeWidgetItem , 每个 QTreeWidgetItem 可以包含多个文本和图标, 每个文本/图标为一个 列.

可以给 QTreeWidget 设置顶层节点(顶层节点可以有多个), 然后再给顶层节点添加子节点, 从而构成树形结构.

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 和 两个按钮.

注意: TreeWidget 是 TreeView 的子类, 功能比 TreeView 更丰富. 咱们使用 TreeWidget 即可.

编写代码, 构造初始数据

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

    // 添加一些子节点
    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 函数

cpp 复制代码
void Widget::on_pushButton_insertTopLevelItem_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_insertItem_clicked()
{
    // 获取到当前选中的节点
    QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();
    if (currentItem == nullptr) 
    {
        return;
    }
    const QString& text = ui->lineEdit->text();
    if(text.isEmpty())
    {
        return;
    }
    QTreeWidgetItem* item = new QTreeWidgetItem();
    item->setText(0, text);
    currentItem->addChild(item);
}

void Widget::on_pushButton_deleteItem_clicked()
{
    // 获取到当前选中的节点
    QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();
    if (currentItem == nullptr) 
    {
        return;
    }
    QTreeWidgetItem* parent = currentItem->parent();
    if(parent == nullptr)
    {
        // 当前节点为顶层节点
        int index = ui->treeWidget->indexOfTopLevelItem(currentItem);
        ui->treeWidget->takeTopLevelItem(index);
    }
    else
    {
        // 普通元素
        parent->removeChild(currentItem);
    }
}

运行结果:

相关推荐
cui_ruicheng2 小时前
C++关联容器进阶:unordered_map / set与详解
开发语言·c++
sycmancia2 小时前
C++——C++异常处理
开发语言·c++
xxxxxxllllllshi2 小时前
java值传递和引用传递的区别?举例一些常见都笔试面试题说明,最后有速记口诀
java·开发语言
HLC++2 小时前
C++中的类和对象
开发语言·c++
setmoon2142 小时前
C++与量子计算模拟
开发语言·c++·算法
KIKIiiiiiiii2 小时前
微信自动化机器人开发
java·开发语言·人工智能·python·微信·自动化
victory04312 小时前
containerd打包命令 和NFS挂载
java·开发语言
野犬寒鸦2 小时前
从零起步学习计算机操作系统:进程篇(知识扩展提升)
java·服务器·开发语言·后端·面试