2

私は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);
}

ありますparentQModelIndex(-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つのフィールドすべてを比較することを知っておく必要があります。rootIndexQPersistentModelIndexrootIndexQModelIndex

つまり、これらのインデックスは両方ともに等しいため、beginInsertRows(QModelIndex(),...)よりparentも等しくなると呼びます。しかし、親よりも呼び出す場合はaになり 、NULL!=であるため、明らかに等しくなりません。ですから、と呼ぶのは悪い考えのようです。rootIndexQMoldeIndex(-1,-1,NULL,NULL)beginInsertRows(createIndex(-1,-1),....)QModelIndex(-1,-1,NULL,<non-null pointer to our model>)rootIndexbeginInsertRows(createIndex(....),....)

Qt内部で何が起こっているのか誰かが私に説明できますか?

(たぶん、この質問を閉じて、Qt内部に関する別のより具体的で具体的な質問を再開する方が良いでしょう。私はそれについて考えます。)

4

1 に答える 1

0

QModelIndexを作成する正しい方法は、row==-1またはcolumn==-1の場合に空のQModelIndexを返すことです。結果QModelIndex内にモデルへのポインターを配置しないことが重要です。uがそうするなら、何かが正しく機能しない可能性があります。

于 2013-04-01T16:02:16.273 に答える