覆盖 QAbstractItemModel::index 并访问 std::map
Posted
技术标签:
【中文标题】覆盖 QAbstractItemModel::index 并访问 std::map【英文标题】:Overriding QAbstractItemModel::index and accessing std::map 【发布时间】:2011-05-08 09:29:25 【问题描述】:在我的程序中,我想将视图/模型模式与 view = QListView 和我自己的模型(我从 QAbstractListModel 子类化)一起使用。我的数据类看起来像
class Avtomat
...
map<QString, State *> states;
...
;
在我的模型类中
class AvtomatModel : public QAbstractListModel
...
Avtomat a;
...
;
我正在尝试重载 QAbstractItemView::index 函数,以便能够提供用于编辑数据映射的界面。 由于索引函数采用 int row 参数,我通过提供以下内容解决了该问题
State* Avtomat::pStateFromIndex(int index) const
map<QString, State *>::const_iterator i;
int count = 0;
for (i = states.begin(); i != states.end() && count != index; ++i)
++count;
return (*i).second;
所以在我的索引函数中我确实喜欢这样
return createIndex(row, column, a.pStateFromIndex(row));
但这看起来很丑,因为我有 O(n)。你能帮我设计一个更好的方法来使用 int index 访问我的地图吗?
【问题讨论】:
【参考方案1】:这是一个基本的数据建模问题。您需要检索数据的主要方式是什么?按键还是按索引?
如果您只通过索引(包括在模型中)访问它,那么您只是使用了不合适的数据结构,应该切换到其他东西,比如列表。
如果您也确实需要按键查询,那么您有多种选择。如果效率不是一个巨大的驱动因素,那么你已经在做的事情没有错,尤其是在数据集很小的情况下。或者,您还可以维护与基础数据的键和索引映射。这是一个简单而有效的解决方案,但它意味着您必须承担管理两者之间一致性的责任,并且如果您的数据集很大,那么内存开销可能会很大。或者,您可以使用直接通过键和索引提供访问的数据结构。最终,这取决于您的具体情况和您正在使用的数据域。
文档中有一个很好的 Qt 容器类(以及 std 容器)summary。 algorithmic complexity 部分可能对您来说特别有趣。
【讨论】:
【参考方案2】:另一种选择是使用向量将数据保存在键值对中。然后可以通过索引或键访问向量。 这样做的缺点是插入向量相对于 std::map 的开销很大。
typedef std::pair<QString, State*> StateP;
typedef std::vector<StateP> States;
States states;
然后根据比较第一个元素的谓词保持向量的排序顺序。您可以通过 O(1) 中的索引或 O(log n) 中的键来查找项目。
struct StatePCompare
bool operator()(StateP const& lhs, StateP const& rhs) const
return (lhs.first < rhs.first);
;
void Avtomat::insert(QString key, State* state)
States::iterator i = std::lower_bound(states.begin(), states.end(), StatePCompare());
if ((i != states.end() && (i->first == key))
// key already exists, set the element
i->second = state;
else
states.insert(i, state);
State* Avtomat::find(QString key)
States::iterator i = std::lower_bound(states.begin(), states.end(), StatePCompare());
if ((i != states.end() && (i->first == key))
return i->second;
return NULL;
【讨论】:
以上是关于覆盖 QAbstractItemModel::index 并访问 std::map的主要内容,如果未能解决你的问题,请参考以下文章