QAbstractItemModel:理解Qt中的模型视图框架

在Qt中,模型视图框架是许多应用程序的核心。这种框架使用模型来表示数据,使用视图(如QTableView或QTreeView)来将该数据可视化。Qt中提供了一些内置的模型类,但是,如果您需要为自己的应用程序定义自定义的数据源,那么您需要了解QAbstractItemModel的工作方式。

一、QAbstractItemModel简介

QAbstractItemModel是Qt的一个关键类,它为开发人员提供了一个接口,用于指定模型数据的组织方式。它是QAbstractTableModel和QAbstractListModel等模型的基类,这些模型提供了一些常见的实现,例如表格和列表。QAbstractItemModel用于QTreeView,QListView,QTableView等视图类的基类,它们都使用基于文件夹的数据模型来显示数据。

QAbstractItemModel所有直接的子类应该在以下一个函数中实现两个不同的索引:index()和parent()。这些函数定义了静态树形结构,元素的位置不会改变。这些函数能够让Qt高效地处理大型树形结构。index()和parent()会被Qt视图类用于将数据排列为TreeView,ListView和TableView等典型模型视图结构。

二、QAbstractItemModel的子类实现

1、自定义QAbstractItemModel

class CustomModel : public QAbstractItemModel
{
public:
    CustomModel(QObject *parent = 0);
    ~CustomModel();

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex &child) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
};

上面是一个自定义的QAbstractItemModel的框架。在这个例子中,根节点是一个空的QModelIndex,它没有坐标以及没有父节点。可以看到,index()和parent()都需要返回一个QModelIndex,它们指定了行和列的位置。rowCount()和columnCount()函数返回模型中行的数量和列的数量。

在此例子中,data()和setData()函数的实现也是必不可少的。它们定义了数据将如何存储和访问。在大多数情况下,将使用QVariant来存储数据,而且在data()函数中使用role参数来返回适合给定视图类型的数据。setData()负责更新模型数据。

2、Qt自带的Model Index

QModelIndex QAbstractItemModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const

index()函数返回一个QModelIndex对象,此对象由行号和列号组成,该索引属于parent。在许多情况下,一些QAbstractItemModel的派生类经常使用这些方法来创建一个自己的index()。

3、返回父级QModelIndex

QModelIndex QAbstractItemModel::parent(const QModelIndex &index) const

parent()函数返回一个QModelIndex对象,该对象传递回索引的父级项的位置。parent()和index()通常应该是相互的逆。parent()为顶级ItemModel或已知索引返回无效的QModelIndex。因此,QModelIndex的行号和列号都是0。

4、获取行数和列数

int QAbstractItemModel::rowCount(const QModelIndex &parent = QModelIndex()) const
int QAbstractItemModel::columnCount(const QModelIndex &parent = QModelIndex()) const

这两个函数返回模型中给定父项的行数或列数。如果没有父项,则返回顶层项的行数或列数。row()和column()一样,都从0开始计数。在许多情况下,这些函数将用于初始化一个ItemView部件。

5、获取和设置ItemData

QVariant QAbstractItemModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const
bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)

data()函数返回与给定模型索引关联的数据。可以为给定角色请求数据。setData()函数将给定值存储在模型索引处。如果此处发生错误,则使用Rollback数据。

三、QAbstractItemModel的应用举例

1、创建树型结构

这个应用程序是一个树型表格。它的数据源是硬编码,但该例子很好地展示了如何扩展QAbstractItemModel来支持树型结构:

class TreeModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    TreeModel(QObject *parent = 0);
    ~TreeModel();

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex &child) const;

    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);

private:
    TreeItem *rootItem;
};

具体的实现过程就不再贴出,可以参考Qt自带例子,这里给出参考:

简易树模型

2、扩展现有的模型类

下面是一个QAbstractItemModel的派生类,该类从QAbstractListModel扩展:

class StringListModel : public QAbstractListModel
{
    Q_OBJECT

public:
    explicit StringListModel(const QStringList &strings, QObject *parent = nullptr)
        : QAbstractListModel(parent), stringList(strings)
    {
    }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override
    {
        if (parent.isValid())
            return 0;
        return stringList.count();
    }

    QVariant data(const QModelIndex &index, int role) const override
    {
        if (!index.isValid())
            return QVariant();

        if (index.row() >= stringList.size())
            return QVariant();

        if (role == Qt::DisplayRole)
            return stringList.at(index.row());
        else
            return QVariant();
    }

private:
    QStringList stringList;
};

StringListModel扩展了QAbstractListModel并实现了rowCount()和data()函数来处理一个QStringList中的内容。这是一个非常基本的示例,但当您需要单行列表模型时,这可能是一个很有用的例子。

3、处理排序和过滤

排序和过滤是QAbstractItemModel的高级应用。排序需要将数据按特定顺序排列,而过滤则需要以某种方式选择数据,例如将其筛选掉。这是一个基本示例:

class SortFilterModel : public QSortFilterProxyModel
{
public:
    SortFilterModel(QObject *parent = nullptr)
        : QSortFilterProxyModel(parent)
    {
    }

    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
    {
        QModelIndex index0 = sourceModel()->index(source_row, 0, source_parent);

        QRegExp regExp("^\\[0-9\\.]+(.*)");
        QString str = index0.data(Qt::DisplayRole).toString();
        if (regExp.indexIn(str) != -1)
        {
            QString capStr = regExp.cap(1);
            if (capStr < "30")
                return false;
        }

        return true;
    }
};

在此示例中,过滤器使用QRegExp来查找所有标题是数字(例如,[20]Title 3)的行。如果标题中的数字小于30,则该行将被过滤掉。

四、总结

QAbstractItemModel为开发者提供了一个用于管理自定义数据的模型视图框架。开发者可以通过继承并实现QAbstractItemModel的相关函数来创建自己的模型,或者继承并扩展现有的模型类。此外,QAbstractItemModel还支持排序和过滤。学会使用QAbstractItemModel可以让应用程序在数据管理方面完美地运转。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/293321.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-26 13:14
下一篇 2024-12-26 13:14

相关推荐

  • TensorFlow Serving Java:实现开发全功能的模型服务

    TensorFlow Serving Java是作为TensorFlow Serving的Java API,可以轻松地将基于TensorFlow模型的服务集成到Java应用程序中。…

    编程 2025-04-29
  • Ojlat:一款快速开发Web应用程序的框架

    Ojlat是一款用于快速开发Web应用程序的框架。它的主要特点是高效、易用、可扩展且功能齐全。通过Ojlat,开发人员可以轻松地构建出高质量的Web应用程序。本文将从多个方面对Oj…

    编程 2025-04-29
  • Zlios——一个多功能的开发框架

    你是否在开发过程中常常遇到同样的问题,需要不断去寻找解决方案?你是否想要一个多功能、易于使用的开发框架来解决这些问题?那么,Zlios就是你需要的框架。 一、简介 Zlios是一个…

    编程 2025-04-29
  • Python训练模型后如何投入应用

    Python已成为机器学习和深度学习领域中热门的编程语言之一,在训练完模型后如何将其投入应用中,是一个重要问题。本文将从多个方面为大家详细阐述。 一、模型持久化 在应用中使用训练好…

    编程 2025-04-29
  • agavi开发框架

    Agavi是一个基于MVC模式的Web应用程序开发框架,以REST和面向资源的设计为核心思想。本文章将从Agavi的概念、优点、使用方法和实例等方面进行详细介绍。 一、概念 Aga…

    编程 2025-04-29
  • Python unittest框架用法介绍

    Python unittest框架是Python自带的一种测试框架,可以用来编写并运行测试用例。在本文中,我们将从以下几个方面详细介绍Python unittest框架的使用方法和…

    编程 2025-04-29
  • com.alipay.sofa.bolt框架

    com.alipay.sofa.bolt框架是一款高性能、轻量级、可扩展的RPC框架。其广泛被应用于阿里集团内部服务以及阿里云上的服务。该框架通过NIO支持高并发,同时还内置了多种…

    编程 2025-04-29
  • ARIMA模型Python应用用法介绍

    ARIMA(自回归移动平均模型)是一种时序分析常用的模型,广泛应用于股票、经济等领域。本文将从多个方面详细阐述ARIMA模型的Python实现方式。 一、ARIMA模型是什么? A…

    编程 2025-04-29
  • Python实现一元线性回归模型

    本文将从多个方面详细阐述Python实现一元线性回归模型的代码。如果你对线性回归模型有一些了解,对Python语言也有所掌握,那么本文将对你有所帮助。在开始介绍具体代码前,让我们先…

    编程 2025-04-29
  • VAR模型是用来干嘛

    VAR(向量自回归)模型是一种经济学中的统计模型,用于分析并预测多个变量之间的关系。 一、多变量时间序列分析 VAR模型可以对多个变量的时间序列数据进行分析和建模,通过对变量之间的…

    编程 2025-04-28

发表回复

登录后才能评论