【问题标题】:QAbstractProxyModel not updating on dataChanged() signalQAbstractProxyModel 未更新 dataChanged() 信号
【发布时间】:2017-10-17 22:22:19
【问题描述】:

这是我在源模型中的setData

bool TreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (!index.isValid() || role != Qt::EditRole)
        return false;

    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
    item->setData(index.column(), value);
    emit dataChanged(index, index);

    return true;
}

我将源模型的dataChanged 信号连接到代理模型的dataChanged 信号,但是只有当我点击它时,显示代理模型的表格视图才会更新。在这种情况下会出现什么问题?我应该以某种方式在代理模型中手动发出dataChanged 信号吗?

来自模型的数据:

QVariant TreeModel::data(const QModelIndex& index, int role) const
{
    if (!index.isValid() || role != Qt::DisplayRole)
        return {};

    TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
    return item->dataAt(index.column());
}

来自 TreeItem:

QVariant TreeItem::dataAt(int n) const
{
    if (n < m_data.size())
        return m_data[n];
    else
        return {};
}

更新: 我认为代理模型应该在来自TreeModel::dataChanged 的索引上使用mapFromSource,但似乎代理不调用mapFromSource,所以我不明白更新是如何发生的。

当我尝试通过代理模型编辑树项目时,同样的行为 - 源模型不会更新它的视图。但是在这种情况下,我可以使用源模型在代理中设置数据:

bool ProxyModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
//    if (!index.isValid() || role != Qt::EditRole)
//        return false;

//    TreeItem* item = static_cast<TreeItem*>(mapToSource(index).internalPointer());
//    item->setData(index.column(), value);
//    emit dataChanged(index, index);

//    return true;

    return sourceModel()->setData(mapToSource(index), value, role);
}

更新: 最后,似乎我几乎明白了。 KDE 的 KDescendantsProxyModel 模型本身发出 dataChanged 信号,所以我还创建了 onSourceDataChanged 插槽并将其连接到源的 dataChanged 信号(它现在只更新第一个索引):

void ProxyModel::onSourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
                                     const QVector<int>& roleNames)
{
    auto index = mapFromSource(topLeft);
    emit dataChanged(index, index);
}

唯一的问题:这是正确的方法还是我做错了什么?

【问题讨论】:

  • 可能,问题出在您的item-&gt;setData。请显示您的 TreeModel::dataTreeItem::setData 方法的代码。顺便说一句,要编写更清晰的代码,不要忘记使用emit 宏:emit dataChanged(index, index);
  • 我在 TreeModel::setData() 方法中发出 dataChanged 信号。显示 TreeModel 的树视图正在按预期更新。
  • 不幸的是,我不知道问题出在哪里。顺便说一句,如果您在代理模型中访问index.internalPointer(),它将无效。您需要直接在源模型索引中访问内部指针。
  • 我认为这取决于索引的创建方式。如果我在代理中创建索引为 createIndex(row, column, s.internalPointer()),其中“s”是源模型的索引 - 代理的索引将包含有效指针。
  • 仅当您自己在代理中创建索引时。因为我在我的项目中遇到了类似的问题。

标签: c++ qt


【解决方案1】:

我将源模型的dataChanged信号连接到代理模式的dataChanged信号

您无法重新发出源模型的信号,因为该信号的索引指向错误的模型。记住dataChanged 的合约:它发出的索引是信号来自的模型上的有效索引。然而,您发出的索引在您的代理模型上无效。

您需要将源的信号连接到插槽或函子,然后将索引映射到代理的索引并发出。

【讨论】:

  • 是的,我更新了我的帖子。我希望你早几个小时回答)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
相关资源
最近更新 更多