2

我有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;
        }
    }

}

它工作正常,但该功能的每一行都让我畏缩。有没有更清洁的方法来做到这一点?

4

3 回答 3

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);
于 2019-06-30T22:24:14.307 回答
2

您需要从您的项目 ID 中获取行索引。

一种更有效的方法是使用 QMap,其中行索引作为值,项目 id 作为键。

在这种情况下,您还需要在每次添加/删除行时维护映射值。

如果您的列表中没有 300 万个项目,请保持简单并使用您的代码。通过优化此代码,您可能还会增加复杂性并降低可维护性,您得到的是 0.05 毫秒而不是 0.06 毫秒。

在 GUI 代码中,我经常有这样的代码:它很简单,每个人都立即得到它并且它完成了工作。它也足够快。

于 2019-06-30T21:38:39.743 回答
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在内部使用它,因此您避免分配StandardItemjust 来获取其索引。在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);
}
于 2019-07-03T10:19:49.443 回答