qt QAbstractItemModel详解

news2024/11/6 6:01:37
1. 概述

QAbstractItemModel是Qt框架中的一个核心抽象基类,在Qt的模型/视图架构中扮演着至关重要的角色。这个类提供了一个接口,用于表示和管理数据,但不直接处理数据的存储。它的主要功能是为视图组件(如QListView、QTableView和QTreeView等)提供一个标准化的接口,使其能够访问和操作数据。通过这种方式,QAbstractItemModel实现了数据处理(模型)与数据展示(视图)的分离,从而简化了复杂数据的管理和展示。

2. 重要方法

QAbstractItemModel类中有多个重要的方法,这些方法使得开发者能够自定义数据的访问和操作方式。以下是一些关键的方法:

  • index(int row, int column, const QModelIndex &parent = QModelIndex()) const:返回给定行、列和父节点的模型索引。
  • parent(const QModelIndex &index) const:返回给定模型索引的父节点的模型索引。
  • rowCount(const QModelIndex &parent = QModelIndex()) const:返回给定父节点下的行数。
  • columnCount(const QModelIndex &parent = QModelIndex()) const:返回给定父节点下的列数。
  • data(const QModelIndex &index, int role = Qt::DisplayRole) const:返回给定模型索引和角色的数据。
  • setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole):将给定模型索引设置为指定的值。
  • moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild):将源模型索引的特定行移动到目标模型索引的特定行位置,并返回移动是否成功的布尔值。

这些方法共同构成了QAbstractItemModel类提供的数据访问和操作接口。

3. 重要信号

QAbstractItemModel类还定义了一些重要的信号,用于通知视图组件数据的更新。以下是一些关键的信号:

  • dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()):当模型中的数据发生变化时,发出此信号以通知视图组件更新显示。
  • layoutChanged():当模型的布局发生变化时(例如,行或列的插入、删除或移动),发出此信号以通知视图组件重新布局。
  • rowsInserted(const QModelIndex &parent, int start, int end):当在给定父节点下插入新行时,发出此信号。
  • rowsRemoved(const QModelIndex &parent, int start, int end):当从给定父节点下删除行时,发出此信号。

这些信号使得视图组件能够响应模型数据的变化,从而保持数据的一致性和准确性。

4、重要角色和标志

以下是QAbstractltemModel类中一些常见的角色和标志及其简要介绍:

角色(Role)
  • Qt::DisplayRole:用于显示的数据。
  • Qt::EditRole:用于编辑的数据。
  • Qt::ToolTipRole:用于显示工具提示的数据。
  • Qt::DecorationRole:用于显示装饰图标的数据。
  • Qt::CheckstateRole:用于显示复选框状态的数据。
标志(Flags)
  • Qt::ItemIsSelectable:项是可选中的。
  • Qt::ItemIsEditable:项是可编辑的。
  • Qt::ItemIsEnabled:项是启用的。
  • Qt::ItemIsUserCheckable:项是用户可复选的。
  • Qt::ItemIsDragEnabled:项可拖拽。
  • Qt::ItemIsDropEnabled:项可放下。

 

 二维表格模型

#include <QApplication>
#include <QMainWindow>
#include <QTableView>
#include <QVariant>
#include <QVector>

class TableModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    TableModel(QObject *parent = nullptr) : QAbstractItemModel(parent)
    {
        // 初始化数据
        dataList = {
            {"Alice", "30", "Engineer"},
            {"Bob", "25", "Designer"},
            {"Charlie", "35", "Manager"}
        };
    }

    // 获取行数
    int rowCount(const QModelIndex &parent = QModelIndex()) const override
    {
        if (parent.isValid()) return 0;
        return dataList.size();
    }

    // 获取列数
    int columnCount(const QModelIndex &parent = QModelIndex()) const override
    {
        if (parent.isValid()) return 0;
        return dataList.isEmpty() ? 0 : dataList[0].size();
    }

    // 获取数据项的值
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
    {
        if (!index.isValid() || role != Qt::DisplayRole)
            return QVariant();
        return dataList[index.row()][index.column()];
    }

    // 标题
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
    {
        if (role != Qt::DisplayRole)
            return QVariant();

        if (orientation == Qt::Horizontal) {
            switch (section) {
                case 0: return "Name";
                case 1: return "Age";
                case 2: return "Occupation";
            }
        }

        return QVariant();
    }

    // 返回指定位置的索引
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
    {
        if (parent.isValid() || !hasIndex(row, column, parent))
            return QModelIndex();
        return createIndex(row, column);
    }

    // 返回父索引
    QModelIndex parent(const QModelIndex &index) const override
    {
        return QModelIndex();
    }

    // 获取数据项的标志属性
    Qt::ItemFlags flags(const QModelIndex &index) const override
    {
        if (!index.isValid())
            return Qt::NoItemFlags;
        return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
    }

private:
    QVector<QVector<QString>> dataList;
};

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

    // 创建主窗口
    QMainWindow mainWindow;
    mainWindow.setWindowTitle("QAbstractItemModel Example");
    mainWindow.resize(400, 300);

    // 创建自定义表模型
    TableModel *model = new TableModel;

    // 创建表视图
    QTableView *tableView = new QTableView;
    tableView->setModel(model);
    tableView->horizontalHeader()->setStretchLastSection(true);
    tableView->setEditTriggers(QAbstractItemView::DoubleClicked);

    // 布局管理
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(tableView);
    QWidget *centralWidget = new QWidget;
    centralWidget->setLayout(layout);

    mainWindow.setCentralWidget(centralWidget);

    // 显示主窗口
    mainWindow.show();

    return app.exec();
}

 树状模型

#include <QApplication>
#include <QMainWindow>
#include <QTreeView>
#include <QVariant>
#include <QVector>

class TreeItem
{
public:
    explicit TreeItem(const QVector<QVariant> &data, TreeItem *parentItem = nullptr)
        : itemData(data), parentItem(parentItem) {}

    ~TreeItem() { qDeleteAll(childItems); }

    void appendChild(TreeItem *child) { childItems.append(child); }
    TreeItem *child(int row) { return childItems.value(row); }
    int childCount() const { return childItems.count(); }
    int columnCount() const { return itemData.count(); }
    QVariant data(int column) const { return itemData.value(column); }
    int row() const { return parentItem ? parentItem->childItems.indexOf(const_cast<TreeItem*>(this)) : 0; }
    TreeItem *parent() { return parentItem;}

private:
    QVector<TreeItem*> childItems;
    QVector<QVariant> itemData;
    TreeItem *parentItem;
};

class TreeModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    TreeModel(QObject *parent = nullptr)
        : QAbstractItemModel(parent)
    {
        QVector<QVariant> rootData {"Title 1", "Title 2"};
        rootItem = new TreeItem(rootData);

        QVector<QVariant> childData1 {"Child 1", "Child Data 1"};
        TreeItem *childItem1 = new TreeItem(childData1, rootItem);
        rootItem->appendChild(childItem1);

        QVector<QVariant> childData2 {"Child 2", "Child Data 2"};
        TreeItem *childItem2 = new TreeItem(childData2, childItem1);
        childItem1->appendChild(childItem2);
    }

    ~TreeModel() { delete rootItem; }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override
    {
        TreeItem *parentItem = parent.isValid() ? static_cast<TreeItem*>(parent.internalPointer()) : rootItem;
        return parentItem->childCount();
    }

    int columnCount(const QModelIndex &parent = QModelIndex()) const override
    {
        TreeItem *parentItem = parent.isValid() ? static_cast<TreeItem*>(parent.internalPointer()) : rootItem;
        return parentItem->columnCount();
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
    {
        if (!index.isValid() || role != Qt::DisplayRole)
            return QVariant();
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        return item->data(index.column());
    }

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override
    {
        if (!hasIndex(row, column, parent))
            return QModelIndex();

        TreeItem *parentItem = parent.isValid() ? static_cast<TreeItem*>(parent.internalPointer()) : rootItem;
        TreeItem *childItem = parentItem->child(row);
        return childItem ? createIndex(row, column, childItem) : QModelIndex();
    }

    QModelIndex parent(const QModelIndex &index) const override
    {
        if (!index.isValid())
            return QModelIndex();

        TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
        TreeItem *parentItem = childItem->parent();

        if (parentItem == rootItem)
            return QModelIndex();

        return createIndex(parentItem->row(), 0, parentItem);
    }

    Qt::ItemFlags flags(const QModelIndex &index) const override
    {
        if (!index.isValid())
            return Qt::NoItemFlags;
        return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
    }

private:
    TreeItem *rootItem;
};

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

    // 创建主窗口
    QMainWindow mainWindow;
    mainWindow.setWindowTitle("QAbstractItemModel Example - Tree");
    mainWindow.resize(400, 300);

    // 创建自定义树模型
    TreeModel *model = new TreeModel;

    // 创建树视图
    QTreeView *treeView = new QTreeView;
    treeView->setModel(model);

    // 布局管理
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(treeView);
    QWidget *centralWidget = new QWidget;
    centralWidget->setLayout(layout);

    mainWindow.setCentralWidget(centralWidget);

    // 显示主窗口
    mainWindow.show();

    return app.exec();
}

#include "main.moc"

觉得有帮助的话,打赏一下呗。。

           

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2234101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试 - 无重复字符的元素长度乘积的最大值(Python/JS/C/C++ 2024 C卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

【C++之STL】一文学会使用 string

文章目录 1. STL导读1. 1 什么是STL1. 2 STL的版本1. 3 STL六大组件1. 4 STL的重要性1. 5 STL的学习1. 6 STL系列博客的规划 2. string2. 1 为什么学习string类?2. 2 标准库中的string2. 3 基本构造2. 4 尾插与输出运算符重载2. 5 构造函数2. 6 赋值运算符重载2. 7 容量操作2.…

【分布式】分布式锁设计与Redisson源码解析

分布式锁 分布式锁是一种在分布式计算环境中用于控制多个节点&#xff08;或多个进程&#xff09;对共享资源的访问的机制。在分布式系统中&#xff0c;多个节点可能需要协调对共享资源的访问&#xff0c;以防止数据的不一致性或冲突。分布式锁允许多个节点在竞争访问共享资源…

【实测有效】两个Ubuntu系统通过网线传输文件

基本思路是&#xff1a;连接网线后&#xff0c;通过设置静态IP&#xff0c;将两台电脑配置在同一个局域网内&#xff0c;再进行文件传输。 一、物理连接 使用网线将两台电脑的网口连接起来。 二、静态IP设置 两台电脑均需要对各自的静态IP进行设置。 1、查看电脑的IP地址 1&a…

Android camera2

一、序言 为了对阶段性的知识积累、方便以后调查问题&#xff0c;特做此文档&#xff01; 将以camera app 使用camera2 api进行分析。 (1)、打开相机 openCamera (2)、创建会话 createCaptureSession (3)、开始预览 setRepeatingRequest (4)、停止预览 stopRepeating (5)、关闭…

【Redis_Day3】Redis通用命令

【Redis_Day3】Redis通用命令 redis客户端的三种形态redis的快与慢redis通用命令阅读redis官方文档redis中两个核心命令set命令get命令 redis全局命令keys命令&#xff1a;查询当前服务器上的key生产环境 exists命令&#xff1a;判定key是否存在del命令&#xff1a;删除指定的k…

静态库、动态库、framework、xcframework、use_frameworks!的作用、关联核心SDK工程和测试(主)工程、设备CPU架构

1.1库的概念 库&#xff1a;程序代码的集合&#xff0c;编译好的二进制文件加上头文件供使用&#xff0c;共享程序代码的一种方式。 1.2库的分类 根据开源情况分为&#xff1a;开源库&#xff08;能看到具体实现&#xff09;、闭源库&#xff08;只公开调用的的接口&#xf…

小菜家教平台:基于SpringBoot+Vue打造一站式学习管理系统

前言 现在已经学习了很多与Java相关的知识&#xff0c;但是迟迟没有进行一个完整的实践&#xff08;之前这个项目开发到一半&#xff0c;很多东西没学搁置了&#xff0c;同时原先的项目中也有很多的问题&#xff09;&#xff0c;所以现在准备从零开始做一个基于SpringBootVue的…

【C++、数据结构】哈希表——散列表(一)(概念/总结)

「前言」 &#x1f308;个人主页&#xff1a; 代码探秘者 &#x1f308;C语言专栏&#xff1a;C语言 &#x1f308;C专栏&#xff1a; C / STL使用以及模拟实现 &#x1f308;数据结构专栏&#xff1a; 数据结构 / 十大排序算法 &#x1f308;Linux专栏&#xff1a; Linux系统编…

山东路远生态科技有限公司竣工投产仪式暨产品发布会圆满举行

第二十届三中全会于2024年7月15日至18日在北京举行。全会审议通过了《关于进一步全面深化改革、推进中国式现代化的决定》。其中提到,“要健全因地制宜发展新质生产力体制机制”。 新质生产力是由技术革命性突破、生产要素创新性配置、产业深度转型升级而催生的当代先进生产力…

MD5(Crypto)

解题思路 打开文件发现一串代码&#xff0c;结合题目提示&#xff0c;应该是 MD5 加密。 找个在线的 MD5 解密网站&#xff0c;行云流水得到 flag。 题目设计原理 题目设计&#xff1a;无他&#xff0c;MD5 加密。 题目原理&#xff1a; MD5&#xff08;Message-Digest Algo…

EHOME视频平台EasyCVR萤石设备视频接入平台视频诊断技术可以识别哪些视频质量问题?

EasyCVR视频监控汇聚管理平台是一款针对大中型项目设计的跨区域网络化视频监控集中管理平台。萤石设备视频接入平台EasyCVR不仅具备视频资源管理、设备管理、用户管理、运维管理和安全管理等功能&#xff0c;还支持多种主流标准协议&#xff0c;如GB28181、GB35114、RTSP/Onvif…

QML项目实战:自定义Button

目录 一.添加模块 ​1.QtQuick.Controls 2.1 2.QtGraphicalEffects 1.12 二.自定义Button 1.颜色背景设置 2.设置渐变色背景 3.文本设置 4.点击设置 5.阴影设置 三.效果 1.当enabled为true 2.按钮被点击时 3.当enabled为false 四.代码 一.添加模块 1.QtQuick.Con…

实战攻略 | ClickHouse优化之FINAL查询加速

【本文作者&#xff1a;擎创科技资深研发 禹鼎侯】 查询时为什么要加FINAL 我们在使用ClickHouse存储数据时&#xff0c;通常会有一些去重的需求&#xff0c;这时候我们可以使用ReplacingMergeTree引擎。这个引擎允许你存储重复数据&#xff0c;但是在merge的时候会根据order …

labview学习总结

labview学习总结 安装labview的特点一、图形化编程范式二、并行执行机制三、硬件集成能力四、应用领域优势五、开发效率六、系统集成能力**labview基本组成示意图****常用程序结构图解**结语 基础知识介绍界面前后面板的概念平铺式和层叠式 帧的概念结构类型顺序结构for循环whi…

Linux 服务器使用指南:从入门到登录

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; &#x1f6a9;博主致力于用通俗易懂且不失专业性的文字&#xff0c;讲解计算机领域那些看似枯燥的知识点&#x1f6a9; 目录 一…

《AI 大模型:重塑软件开发新未来》

引言 在科技的璀璨星河中&#xff0c;AI 大模型宛如一颗耀眼的新星&#xff0c;正以前所未有的力量改写着软件开发的篇章。随着其技术的持续演进&#xff0c;软件开发流程正经历着翻天覆地的变化。从代码自动生成的神奇魔法&#xff0c;到智能测试的精准洞察&#xff0c;AI 大…

acmessl.cn提供接口API方式申请免费ssl证书

目录 一、前沿 二、API接口文档 1、证书可申请列表 简要描述 请求URL 请求方式 返回参数说明 备注 2、证书申请 简要描述 请求URL 请求方式 业务参数 返回示例 返回参数说明 备注 3、证书查询 简要描述 请求URL 请求方式 业务参数 返回参数说明 备注 4、证…

windows server2019下载docker拉取redis等镜像并运行项目

一、基本概念 1、windows server 指由微软公司开发的“Windows”系列中的“服务器”版本。这意味着它是基于Windows操作系统的&#xff0c;但专门设计用于服务器环境&#xff0c;而不是普通的桌面或个人用户使用。主要用途包括服务器功能、用户和资源管理、虚拟化等 2、dock…

Docker-- cgroups资源控制实战

上一篇&#xff1a;容器化和虚拟化 什么是cgroups&#xff1f; cgroups是Linux内核中的一项功能&#xff0c;最初由Google的工程师提出&#xff0c;后来被整合进Linux内核; 它允许用户将一系列系统任务及其子任务整合或分隔到按资源划分等级的不同组内&#xff0c;从而为系统…