QML ListView在endInsertRows()之后不更新信息

时间:2013-03-27 11:34:25

标签: listview models qml

我正在尝试使用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如何处理模型中的变化以及表示插入行的正确方法是什么?

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

P.P.S。在debuggin之后,我意识到了什么是错的

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 ++版本的一些实验后,我发现了这个bug的原因。在上面的成员_q_rowsInserted中,我们在beginInserRows()中提交的值rootIndex是类QPersistentModelIndex的对象。 rootIndex通常等于QModelIndex(-1,-1,NULL,NULL)。另外你应该知道class QModelIndex的operator ==比较了这个类的所有4个字段。

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

有人能解释一下Qt内部会发生什么吗?

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

1 个答案:

答案 0 :(得分:0)

创建QModelIndex的正确方法是,如果row == - 1或column == - 1,则返回空的QModelIndex。重要的是不要在结果QModelIndex中放置指向模型的指针。如果你愿意的话,某些东西可能无法正常工作。