私は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がモデルの変更を処理する方法と、行が挿入されたことを通知する正しい方法を教えてください。
PSソースファイルが役立つかどうかはわかりませんが、これはソースツリー全体であり、ソースの中で最も興味深い場所です。
PPSデバッグ後、何が悪いのか気づきました
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);
}
ありますparent
が QModelIndex(-1,-1,0x0,AbstractModel(0xfa9690) )
、rootIndex
等しくQModelIndex(-1,-1,0x0,QObject(0x0) )
ありません。そのため、イベントは発生しません。なぜこれが起こるのかを理解するためにもっと時間が必要です....
PPPS同じアプリケーションの純粋なC++バージョンでいくつかの実験を行った後、このバグの理由を発見しました。上記のメンバー_q_rowsInserted
では、親はクラスのisオブジェクトで送信しbeginInserRows()
た値です。通常、QModelIndex(-1、-1、NULL、NULL)と同じです。また、クラスのoperator ==は、このクラスの4つのフィールドすべてを比較することを知っておく必要があります。rootIndex
QPersistentModelIndex
rootIndex
QModelIndex
つまり、これらのインデックスは両方ともに等しいため、beginInsertRows(QModelIndex(),...)
よりparent
も等しくなると呼びます。しかし、親よりも呼び出す場合はaになり 、NULL!=であるため、明らかに等しくなりません。ですから、と呼ぶのは悪い考えのようです。rootIndex
QMoldeIndex(-1,-1,NULL,NULL)
beginInsertRows(createIndex(-1,-1),....)
QModelIndex(-1,-1,NULL,<non-null pointer to our model>)
rootIndex
beginInsertRows(createIndex(....),....)
Qt内部で何が起こっているのか誰かが私に説明できますか?
(たぶん、この質問を閉じて、Qt内部に関する別のより具体的で具体的な質問を再開する方が良いでしょう。私はそれについて考えます。)