自学内容网 自学内容网

qt QAbstractItemModel详解

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"

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

           


原文地址:https://blog.csdn.net/ckg3824278/article/details/143515934

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!