如何有效地查找 QAbstractTableModel::data 中的项目?

Posted

技术标签:

【中文标题】如何有效地查找 QAbstractTableModel::data 中的项目?【英文标题】:How to efficiently lookup items in QAbstractTableModel::data? 【发布时间】:2021-11-01 19:43:51 【问题描述】:

据我所见,Qt 文档和大多数在线示例假定我们对data() 中基于(列、行)的查找感到满意。但是如果我的表是基于自定义结构的呢?例如让我们有:

struct MyDrive

    QString serialNo;
    QString user;
    QString pc;
    QString ipAddress;
    QString category;
;

serialNo 是关键。因此,来自外部的任何操作(想象模型已实现侦听器)都使用它来删除/修改项目,使 QMap 成为理想的候选对象。

但是如何将这个结构与QModelIndex的数据联系起来呢? QAbstractTableModel::data 要求以 (column,row) 作为键的数据,使其更适合 QVector<QVector>> 或类似的东西(我读到的地方我应该避免在 data() 中使用具有非恒定访问时间的容器(如 map)) .

我可以想象使用一个以QModelIndex 作为键和serialNo 作为值的映射,它将用作我的(基于序列号的)映射的键,但这看起来非常低效——QModelIndex 地址毕竟具体的条目(序列号,用户,个人电脑,...),所以我们会一遍又一遍地复制同一个项目。我也在考虑使用<serialNo, MyDrive*> 映射,但这只是一个丑陋的设计决策的解决方法。

我不敢相信我是第一个遇到这种情况的人,那么它通常是如何解决的?

【问题讨论】:

您需要继承 QAbstractItemModel 并覆盖索引。使用 createIndex 并将指针传递给您的数据结构 @linuxfever 是的,与此同时我已经想通了,但仍然......你会传递给指针什么?整体结构?对于每一列?对我来说似乎有点低效...... 你能描述一下你希望你的表格视图是什么样子吗?是否以 user、pc、ipadress 和 category 作为列的单行? @linuxfever 完全正确(加上序列号)。提供记录但与它们一起工作没有问题。在我看来,我必须选择是否需要一种有效的方式来修改它们或呈现它们,但不是两者兼而有之。 我正在为您准备答案。我假设您有很多 MyDrive 实例。这些是如何存储的?矢量? 【参考方案1】:

您可以使用 QAbstractItemModel::match 按序列查找项目 qt help 并将所有必要的数据输入表中。这将允许您不使用容器,但这是一个效率如何的问题......

第二种解决方案是 AbstractItemModel Reference 的子类。现在你可以通过实现 data() 函数来做你想做的事并使用任何容器。

【讨论】:

【参考方案2】:

我可能误解了您所面临的问题,但我们开始吧。我假设你有很多MyDrive 的实例。这是 QAbstractTableModel 子类的(不完整)实现。诀窍是将 MyDrive 的正确实例传递给适当的 QModelIndex。当您稍后修改或访问该索引中的数据时,您不再需要使用 serialNo 了,因为该索引的内部指针是您在创建该索引时传递的 MyDrive 实例:

class MyTable : public QAbstractTableModel

public:
    
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
    
        auto* my_drive = static_cast<MyDrive*>(index.internalPointer());
        auto drive_key = my_drive->serialNo;
        // use the key if you desire for lookups etc
        //...
        //        return your data;
    
    
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
    
        auto* my_drive = static_cast<MyDrive*>(index.internalPointer());
        auto drive_key = my_drive->serialNo;
        // use they key again if you like
    
    
    QModelIndex index(int row, int column, const QModelIndex &parent) const
    
        // insert checks here for parent and to ensure row and column are within appropriate bounds etc
        // your returned index will now store your MyDrive instance which you will later access from the data and setData methods
        return createIndex(row, column, m_data + row);
    
    
private:
    
    // array of MyDrive instances
    MyDrive* m_data;
;

【讨论】:

好的,但是现在您将如何从外部更改特定的 MyDrive? IE。现在我想修改 seriaNo = 1234 的记录(例如更改其 IP 地址)。这就是我所说的意思——现在你让它易于呈现,但不容易从外部修改(现在我知道我应该更具体地说明修改步骤)。

以上是关于如何有效地查找 QAbstractTableModel::data 中的项目?的主要内容,如果未能解决你的问题,请参考以下文章

如何有效地查找包含列表中项目的数据框行?

如何根据关键和时间间隔有效地查找父记录?

Core Data,我如何有效地查找和删除托管对象

在 Oracle 中独立地从多个列中有效地查找前 N 个值

如何在图像处理中有效地使用线程?

如何将多个查找和替换转换为更有效的循环