通过项目数据从 QStandardItemModel 中查找/删除一行
Finding / removing a row from a QStandardItemModel by item data
我有一个只有一列的 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;
}
}
}
它工作正常,但该函数的每一行都让我感到畏缩。有没有更简洁的方法来执行这些操作?
您需要从项目 ID 中获取行索引。
一种更有效的方法可能是使用 QMap,其中行索引作为值,项目 ID 作为键。
在这种情况下,您还需要在每次 add/remove 行时维护地图值。
如果您的列表中没有 300 万个项目,请保持简单并使用您的代码。
通过优化此代码,您可能还会增加复杂性并降低可维护性,并且您得到的是 0.05 毫秒而不是 0.06 毫秒。
在 GUI 代码中,我经常有这样的代码:它很简单,每个人都能立即理解并完成工作。它也足够快。
直接遍历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
它 returns 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);
你使用的findItems
错了,它已经可以return你想要的项目,只需传递你要搜索的值。如果您像现在这样称呼它,那么您至少要遍历您的项目两次,因为 findItems
必须遍历所有项目以找到与您的模式匹配的项目,在您的情况下,所有项目都匹配,然后您再次迭代 returned 项目以找到 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
returns 紧跟在与模式匹配的项目数之后,在本例中是 sessionId
的值,因此它并不总是迭代所有项目;这样更有效率。显然,如果在迭代所有项目后未找到该值,则它 return 是一个空列表。
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);
}
我有一个只有一列的 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;
}
}
}
它工作正常,但该函数的每一行都让我感到畏缩。有没有更简洁的方法来执行这些操作?
您需要从项目 ID 中获取行索引。
一种更有效的方法可能是使用 QMap,其中行索引作为值,项目 ID 作为键。
在这种情况下,您还需要在每次 add/remove 行时维护地图值。
如果您的列表中没有 300 万个项目,请保持简单并使用您的代码。 通过优化此代码,您可能还会增加复杂性并降低可维护性,并且您得到的是 0.05 毫秒而不是 0.06 毫秒。
在 GUI 代码中,我经常有这样的代码:它很简单,每个人都能立即理解并完成工作。它也足够快。
直接遍历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
它 returns 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);
你使用的findItems
错了,它已经可以return你想要的项目,只需传递你要搜索的值。如果您像现在这样称呼它,那么您至少要遍历您的项目两次,因为 findItems
必须遍历所有项目以找到与您的模式匹配的项目,在您的情况下,所有项目都匹配,然后您再次迭代 returned 项目以找到 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
returns 紧跟在与模式匹配的项目数之后,在本例中是 sessionId
的值,因此它并不总是迭代所有项目;这样更有效率。显然,如果在迭代所有项目后未找到该值,则它 return 是一个空列表。
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);
}