当前位置: 首页 > news >正文

QT:模型视图代理

Qt Model/View/Delegate(MVD)框架,它是 Qt 中用于实现数据显示和编辑的一种架构模式,主要由模型(Model)、视图(View)和委托(Delegate)三部分组成,以下是对其概念的详细介绍:

模型(Model)

角色:模型是 MVD 框架的核心部分,主要负责存储和管理数据。它提供了一种统一的接口,用于访问和操作各种类型的数据,如数组、列表、表格数据等,而不依赖于具体的数据存储方式。
功能:模型负责提供数据给视图进行显示,同时也处理来自视图的用户交互操作,如数据的插入、删除、修改等。它通过信号和槽机制与视图和委托进行通信,当数据发生变化时,模型会发出信号通知视图进行更新。
常用类:在 Qt 中,有多种模型类可供使用,如QStandardItemModel用于处理标准的列表和表格数据,QFileSystemModel用于处理文件系统相关的数据,QSqlTableModel用于与数据库表进行交互等。

视图(View)

角色:视图主要负责数据的可视化展示,它从模型中获取数据,并以特定的方式将数据呈现给用户,如以列表、表格、树状等形式显示。
功能:视图负责接收用户的输入操作,如鼠标点击、键盘输入等,并将这些操作转换为对模型的请求。例如,当用户在表格视图中点击某个单元格时,视图会将这个操作传递给模型,以便模型进行相应的处理。同时,视图会根据模型发出的信号来更新自身的显示,以反映数据的变化。
常用类:Qt 提供了多种视图类,如QListView用于显示列表数据,QTableView用于显示表格数据,QTreeView用于显示树状结构数据等。

委托(Delegate)

角色:委托用于控制数据在视图中的编辑和显示方式,它提供了一种自定义数据显示和编辑行为的机制。
功能:在视图中,当用户需要编辑数据时,委托会提供相应的编辑组件,如文本框、下拉列表等,让用户进行编辑。委托还可以对用户输入的数据进行验证和格式化处理,确保数据的合法性和一致性。
常用类:Qt 中常用的委托类是QStyledItemDelegate,它提供了基本的委托功能。用户可以通过继承QStyledItemDelegate类来实现自定义的委托,以满足特定的需求。

QAbstractItemModel

在 Qt 中,QAbstractItemModel 是所有模型类的抽象基类,它为数据模型提供了一个通用的接口,使得数据可以被不同的视图(如 QListView、QTableView、QTreeView 等)显示和操作。从 QAbstractItemModel 派生出了许多具体的模型类

QStandardItemModel

用途:QStandardItemModel 是一个通用的模型类,用于存储标准项(QStandardItem)的数据。它可以处理列表、表格和树状结构的数据,非常适合简单的数据管理和显示。

#include <QApplication>
#include <QStandardItemModel>
#include <QTableView>
#include <QDebug>

// 槽函数,用于处理数据更改信号
void printCellData(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) {
    Q_UNUSED(roles);
    // 将 model 声明为 const QAbstractItemModel* 类型
    const QAbstractItemModel *model = topLeft.model();
    // 遍历更改的单元格范围
    for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
        for (int col = topLeft.column(); col <= bottomRight.column(); ++col) {
            QModelIndex index = model->index(row, col);
            QVariant data = model->data(index);
            qDebug() << "Row:" << row << "Column:" << col << "Data:" << data.toString();
        }
    }
}

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    // 创建一个 QStandardItemModel,有 3 行 2 列
    QStandardItemModel model(3, 2);

    // 设置表头
    model.setHorizontalHeaderLabels({"Name", "Age"});

    // 设置单元格数据
    QStandardItem *item1 = new QStandardItem("Alice");
    model.setItem(0, 0, item1);

    QStandardItem *item2 = new QStandardItem("25");
    model.setItem(0, 1, item2);

    // 创建一个表格视图并设置模型
    QTableView tableView;
    tableView.setModel(&model);

    // 连接模型的数据更改信号到槽函数
    QObject::connect(&model, &QStandardItemModel::dataChanged, printCellData);

    tableView.show();

    return a.exec();
}

在这里插入图片描述

QFileSystemModel

用途:QFileSystemModel 用于表示文件系统的目录和文件结构。它可以方便地在视图中显示文件系统的内容,支持文件和文件夹的浏览、排序等操作。

#include <QApplication>
#include <QFileSystemModel>
#include <QTreeView>
#include <QDebug>

// 槽函数,用于处理树状视图的点击事件
void printClickedItemInfo(const QModelIndex &index) {
    const QFileSystemModel *model = qobject_cast<const QFileSystemModel*>(index.model());
    if (model) {
        // 获取文件或文件夹的路径
        QString filePath = model->filePath(index);
        // 获取文件或文件夹的名称
        QString fileName = model->fileName(index);
        // 判断是文件还是文件夹
        bool isDir = model->isDir(index);

        qDebug() << "Clicked Item Information:";
        qDebug() << "Name:" << fileName;
        qDebug() << "Path:" << filePath;
        qDebug() << "Is Directory:" << (isDir ? "Yes" : "No");
    }
}

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    // 创建一个 QFileSystemModel
    QFileSystemModel model;
    // 设置根路径
    model.setRootPath(QDir::homePath());

    // 创建一个树状视图并设置模型
    QTreeView treeView;
    treeView.setModel(&model);
    // 设置显示的根目录
    treeView.setRootIndex(model.index(QDir::homePath()));

    // 连接树状视图的 clicked 信号到槽函数
    QObject::connect(&treeView, &QTreeView::clicked, printClickedItemInfo);

    treeView.show();

    return a.exec();
}

在这里插入图片描述

QSqlTableModel

用途:QSqlTableModel 用于与数据库中的单个表进行交互。它提供了一种简单的方式来显示、编辑和管理数据库表中的数据。

#include <QApplication>
#include <QSqlDatabase>
#include <QSqlTableModel>
#include <QTableView>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>

// 创建表并插入示例数据
void setupDatabase(QSqlDatabase &db) {
    QSqlQuery query(db);

    // 创建 people 表
    if (!query.exec("CREATE TABLE IF NOT EXISTS people ("
                    "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                    "name TEXT, "
                    "age INTEGER)")) {
        qDebug() << "Table creation error:" << query.lastError().text();
        return;
    }

    // 插入示例数据
    if (!query.exec("INSERT INTO people (name, age) VALUES ('Alice', 25)")) {
        qDebug() << "Data insertion error:" << query.lastError().text();
    }
    if (!query.exec("INSERT INTO people (name, age) VALUES ('Bob', 30)")) {
        qDebug() << "Data insertion error:" << query.lastError().text();
    }
}

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    // 连接数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("test.db");
    if (!db.open()) {
        qDebug() << "Database open error:" << db.lastError().text();
        return 1;
    }

    // 设置数据库,创建表并插入数据
    setupDatabase(db);

    // 创建一个 QSqlTableModel
    QSqlTableModel model;
    // 设置要操作的表名
    model.setTable("people");
    // 选择表中的数据
    model.select();

    // 创建一个表格视图并设置模型
    QTableView tableView;
    tableView.setModel(&model);
    tableView.show();

    return a.exec();
}

setupDatabase 函数:
该函数接受一个 QSqlDatabase 引用作为参数,用于在数据库中创建表并插入示例数据。
使用 QSqlQuery 执行 SQL 语句,CREATE TABLE IF NOT EXISTS 用于创建 people 表,如果该表不存在的话。
接着使用 INSERT INTO 语句插入两条示例数据。
main 函数:
连接到 SQLite 数据库 test.db,如果打开失败则输出错误信息并退出程序。
调用 setupDatabase 函数,创建表并插入示例数据。
创建 QSqlTableModel 并设置要操作的表名为 people,然后调用 select() 方法从表中选择数据。
创建 QTableView 并将模型设置给它,最后显示表格视图。
在这里插入图片描述

QSqlQueryModel

用途:QSqlQueryModel 用于执行 SQL 查询并显示查询结果。它是一个只读模型,不支持直接编辑数据,但可以方便地显示数据库查询的结果。

#include <QApplication>
#include <QSqlDatabase>
#include <QSqlQueryModel>
#include <QTableView>
#include <QSqlError>
#include <QDebug>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    // 连接数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("test.db");
    if (!db.open()) {
        qDebug() << "Database open error:" << db.lastError().text();
        return 1;
    }

    // 创建一个 QSqlQueryModel
    QSqlQueryModel model;
    // 执行 SQL 查询
    model.setQuery("SELECT * FROM people");

    // 创建一个表格视图并设置模型
    QTableView tableView;
    tableView.setModel(&model);
    tableView.show();

    return a.exec();
}

在这里插入图片描述

功能特点

  1. QSqlQueryModel
    只读性:QSqlQueryModel 是一个只读模型,它主要用于执行 SQL 查询并显示查询结果,不支持直接对数据进行编辑、插入或删除操作。这是因为它设计的初衷是简单地呈现查询到的数据,不提供修改数据的接口,以保证数据的安全性和一致性。
    灵活性:它非常灵活,可以执行任意的 SQL 查询语句,无论是简单的 SELECT 查询,还是复杂的多表连接查询、带有条件和排序的查询等,都能轻松应对。你可以根据自己的需求构造不同的 SQL 查询语句,然后将结果显示在视图中。
    数据处理:QSqlQueryModel 只是简单地将查询结果存储在模型中,并提供给视图进行显示,不负责对数据进行额外的处理或维护。例如,它不会跟踪数据的修改状态,也不会自动更新数据库中的数据。
  2. QSqlTableModel
    可编辑性:QSqlTableModel 支持对数据进行编辑、插入和删除操作。它提供了一系列的接口,如 setData() 用于修改数据,insertRows() 用于插入新行,removeRows() 用于删除行等。当你对模型中的数据进行修改后,可以调用 submitAll() 或 revertAll() 方法来提交或撤销这些修改,并且这些修改会自动反映到数据库中。
    单表操作:QSqlTableModel 主要用于与数据库中的单个表进行交互,它只能操作一个指定的表。在使用时,你需要通过 setTable() 方法指定要操作的表名,然后可以对该表中的数据进行各种操作。
    数据同步:QSqlTableModel 会自动跟踪数据的修改状态,确保模型中的数据与数据库中的数据保持同步。当你对模型中的数据进行修改后,调用 submitAll() 方法时,它会将这些修改应用到数据库中;调用 revertAll() 方法时,会将模型中的数据恢复到上次从数据库中读取的状态。

使用场景

  1. QSqlQueryModel
    当你只需要显示数据库中的数据,而不需要对数据进行编辑时,可以使用 QSqlQueryModel。例如,显示数据库中的统计报表、查询结果列表等。
    当你需要执行复杂的 SQL 查询,并且不需要对查询结果进行修改时,QSqlQueryModel 是一个很好的选择。因为它可以执行任意的 SQL 查询,并且能够快速地将查询结果显示在视图中。
  2. QSqlTableModel
    当你需要对数据库中的单个表进行数据的编辑、插入和删除操作时,应该使用 QSqlTableModel。例如,开发一个数据库管理系统,需要对用户信息表进行增删改查操作,就可以使用 QSqlTableModel。
    当你需要确保模型中的数据与数据库中的数据保持同步时,QSqlTableModel 能够很好地满足需求。它会自动处理数据的更新和同步,减少了开发者的工作量。

相关文章:

  • 深入剖析 OpenCV:全面掌握基础操作、图像处理算法与特征匹配
  • 小程序中的插槽(Slot)机制及其与 Vue 组件的异同
  • Ubuntu下QT安装和调试的常见问题(一)__could_not_dertermine_which_make
  • Python在实际工作中的运用-合并XLSX表格的新方法
  • FPGA AXI-Stream协议详解与仿真实践
  • Python异常处理面试题及参考答案
  • C++ STL(三)list
  • YOLOv12架构深度解析:关键架构特征的细分
  • Python多线程知多少
  • 手机打电话时如何识别对方按下的DTMF按键的字符-安卓AI电话机器人
  • cpp单调栈模板
  • DeepSeek如何辅助学术量化研究
  • 基于coze+微信小程序实现图片上传并利用大模型解析
  • TP-LINK路由器如何设置网段、网关和DHCP服务
  • 左值引用与右值引用详解
  • 第二十八:5.5.【storeToRefs】5.6.【getters】
  • Ultralytics导出的Engine模型直接加载报错
  • DeepSeek 损失函数、奖励函数、训练过程
  • Docker01 - docker快速入门
  • MFC获取所有硬件厂商和序列号
  • 国家防汛抗旱总指挥部对15个重点省份开展汛前实地督导检查
  • 杨文庄当选中国人口学会会长,曾任国家卫健委人口家庭司司长
  • 外企聊营商|特雷通集团:税务服务“及时雨”
  • 75万买299元路由器后续:重庆市纪委、财政局、教委联合调查
  • 受贿3501万余元,中石油原董事长王宜林一审被判13年
  • 国家林业和草原局原党组成员、副局长李春良接受审查调查