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/zh-tw/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

發表回復

登錄後才能評論