【问题标题】:QML ListView does not update information after endInsertRows()QML ListView 在 endInsertRows() 之后不更新信息
【发布时间】:2013-03-27 11:34:25
【问题描述】:

我正在试验 C++、QML 和 OCaml。现在我正在解决一个奇怪的问题:如果我在模型中添加新行,QML 不会自行更新。是的,我知道 beginInsetRows()...endInsertRows()。

我的模型有 1 列和 1 行。我想再添加 1 行并调用 beginInsertRows(QModelIndex(-1,-1), 1, 1),进行一些计算并调用 endInsertRows()。我添加了一些调试输出到qt5/qtbase/src/corelib/itemmodels/qabstractitemmodel.cpp

void QAbstractItemModel::endInsertRows()
{
Q_D(QAbstractItemModel);
    qDebug() << "Insert QAbstractItemModel::endInsertRows()";
    QAbstractItemModelPrivate::Change change = d->changes.pop();
    d->rowsInserted(change.parent, change.first, change.last);
    qDebug() << "emitting rowsInserted("<<change.parent<<","<<change.first<<","<<change.last<<")";
    emit rowsInserted(change.parent, change.first, change.last, QPrivateSignal());
}

根据我的应用程序日志信号rowsInserted 应该被发出。

Going to call AbstractModel::beginInsertRows 
Calling AbstractModel::rowCount 
rowCount = 1
Going to call AbstractModel::endInsertRows 
Insert QAbstractItemModel::endInsertRows() 
emitting rowsInserted( QModelIndex(-1,-1,0x0,AbstractModel(0x11d3680) )  , 1 , 1 ) 
End inserting rows. cpp_data.length = 2
Sending event to change model
Call update (0,0)...(1,0)
Going to call AbstractModel::dataChanged 
Calling AbstractModel::parent

然后我开始思考如何实现 ListView 以及它如何处理有关添加新行的信号。 grep 命令的输出真的让我大吃一惊:

......./qt5/qtdeclarative/src/quick/items$ grep rowsInserted qquicklistview* 
......./qt5/qtdeclarative/src/quick/items$

那么,您能否解释一下 ListView 如何处理模型中的更改以及表示已插入行的正确方法是什么?

附:我不知道是否有任何源文件有用,但这是whole source tree,这是the most interesting place in the sources

P.P.S.调试后我意识到出了什么问题

void QQuickVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
{
    Q_D(QQuickVisualDataModel);
    if (parent == d->m_adaptorModel.rootIndex)
        _q_itemsInserted(begin, end - begin + 1);
}

parentQModelIndex(-1,-1,0x0,AbstractModel(0xfa9690) )rootIndexQModelIndex(-1,-1,0x0,QObject(0x0) ) 并且它们不相等,这就是不引发事件的原因。需要更多时间来了解为什么会发生这种情况......

P.P.P.S.在对同一应用程序的纯 C++ 版本进行了一些实验后,我发现了这个错误的原因。在上面的成员_q_rowsInserted 中,父级是我们在beginInserRows() 中提交的值,rootIndex 是类QPersistentModelIndex 的对象。 rootIndex 通常等于 QModelIndex(-1,-1,NULL,NULL)。您还应该知道 QModelIndex 类的 operator== 比较该类的所有 4 个字段。

即如果我们调用beginInsertRows(QModelIndex(),...) 而不是parent 将等于rootIndex,因为这些索引都等于QMoldeIndex(-1,-1,NULL,NULL)。但是如果我们调用beginInsertRows(createIndex(-1,-1),....),那么我们的父级将是QModelIndex(-1,-1,NULL,&lt;non-null pointer to our model&gt;),它显然不等于rootIndex,因为NULL !=。所以,打电话给beginInsertRows(createIndex(....),....)似乎是个坏主意。

谁能解释一下 Qt 内部发生了什么?

(也许现在最好关闭这个问题并重新打开另一个关于 Qt 内部的更具体和具体的问题。我会考虑的。)

【问题讨论】:

  • 这个问题是否与 OCaml 相关联?如果没有,请移除 ocaml 标签。
  • 我认为最好按原样说,因为我不直接调用 C++ 方法,它们都被包装到 OCaml 值。
  • 据我所知,没有公共 QModelIndex(int, int) 构造函数,所以我很惊讶它可以编译。你试过 QModelIndex() 吗?
  • QModelIndex() 与 QModelIndex(-1,-1) 相同

标签: listview models qml


【解决方案1】:

创建 QModelIndex 的正确方法是在 row==-1 或 column==-1 时返回空 QModelIndex。重要的是不要将指向模型的指针放在结果 QModelIndex 中。如果你这样做,有些事情可能无法正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 2019-07-28
    • 2020-04-09
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多