我有一个QStandardItemModel
,其中只有一列(代表一个列表)。列表中的每个项目都有一个唯一的整数ID,作为QStandardItem
的数据存储(通过QStandardItem::setData
,我猜默认是通过Qt::UserRole+1
来存储的。)
给出这些ID之一,我想从模型中查找并删除相应的行。现在我正在这样做:
void NetworkManager::removeSessionFromModel (QStandardItemModel *model, int sessionId) {
foreach (const QStandardItem *item, model->findItems("*", Qt::MatchWildcard)) {
if (item->data() == sessionId) {
model->removeRow(item->index().row());
break;
}
}
}
它工作正常,但是该功能的每一行都让我畏缩。有没有一种更清洁的方法可以做到这一点?
答案 0 :(得分:4)
直接遍历QStandardItemModel
怎么样?像这样:
void NetworkManager::removeSessionFromModel (QStandardItemModel *model, int sessionId)
{
for (int i = 0; i < model->rowCount(); ++i)
{
if (model->item(i)->data() == sessionId)
{
model->removeRow(i);
break;
}
}
}
不确定QStandardItemModel
在随机访问下的行为,也许您的方法更有效。
编辑:
实际上,有一个函数可以执行您想要的操作:QAbstractItemModel::match
它返回一个QModelIndexList
,其中所有条目在给定角色中具有匹配的数据。
void NetworkManager::removeSessionFromModel (QStandardItemModel *model, int sessionId)
{
QModelIndexList list = model->match(model->index(0, 0), Qt::UserRole + 1, sessionId);
if (!list.empty())
model->removeRow(list .first().row());
}
可以按照以下步骤将数据设置为特定角色:
model->setData(model->index(row, col), QVariant(13), Qt::UserRole + 1);
答案 1 :(得分:2)
您需要从商品ID中获取行索引。
一种更有效的方法是使用QMap,将行索引作为值,并将项目ID作为键。
在这种情况下,每次添加/删除行时,您还需要维护地图值。
如果列表中没有3百万个项目,请保持简洁并使用代码。 通过优化此代码,您可能还增加了复杂性并降低了可维护性,得到的是0.05毫秒而不是0.06毫秒。
在GUI代码中,我经常有这样的代码:很简单,每个人都立即得到它并且可以完成工作。它也足够快。
答案 2 :(得分:1)
您使用的findItems
错误,仅通过传递您要搜索的值就可以返回所需的项目。如果您像现在这样操作就称呼它,那么您至少要遍历两次项目,因为findItems
必须遍历所有项目以找到与您的模式相匹配的项目,在这种情况下,所有项目都应匹配,然后您再次迭代返回的项目以找到sessionId
。
void NetworkManager::removeSessionFromModel (QStandardItemModel *model, int sessionId) {
auto items = model->findItems(QString::number(sessionId));
if (!items.empty()) {
auto row = items.first()->index().row();
model->removeRow(row);
}
}
您也可以使用match方法,因为findItems
在内部使用该方法,因此避免分配StandardItem
只是为了获取其索引。同样,在找到与模式匹配的项目数(在这种情况下为match
的值)之后,sessionId
会立即返回,因此它并不总是迭代所有项目。这样更有效。显然,如果在迭代所有项目后都找不到该值,它将返回一个空列表。
auto start = model->index(0, 0);
auto indexes = model->match(start, Qt::UserRole + 1, QString::number(sessionId), 1, Qt::MatchExactly);
if (!indexes.empty()) {
auto row = indexes.first().row();
model->removeRow(row);
}