QModelIndexを新しい行に関連付ける方法は?
-
25-10-2019 - |
質問
私は調理しました QAbstractListModel
モデルインデックスには、データを処理するために必要なポインターが含まれています。次のようなデータを追加します:
void PointListModel::addPoint(int frameNumber, QPoint const& pos)
{
PointItem *pointItem = new PointItem( frameNumber, pos );
QModelIndex newRow = this->createIndex( m_points.count(), 0, pointItem );
qDebug() << newRow.internalPointer();
beginInsertRows( newRow, m_points.count(), m_points.count() );
m_points.insert( m_points.count( ), pointItem );
endInsertRows();
emit pointAdded( pointItem, pos );
}
私が議論が beginInsertRows
を求めています 親 新しい行の実際のモデルインデックスではなく、新しい行のモデルインデックス。
したがって、この時点で、QTは私に供給する方法を与えてくれませんでした QModelIndex
この特定の行に関連付けます。この新しい行の独自のモデルインデックスを作成するにはどうすればよいですか?
解決
さて、私は自分の答えを書き直しています。いくつかの調査の後、私はそれが間違っていることを発見しました。
新しいデータを追加するときに、新しいインデックスを作成するために特別なことをするべきではありません。コードは次のようになります。
PointItem *pointItem = new PointItem( frameNumber, pos );
// assume you insert a top level row, having no parent
beginInsertRows( QModelIndex(), m_points.count(), m_points.count() );
m_points.insert( m_points.count( ), pointItem );
endInsertRows();
次に、実装する必要があります index()
オンデマンドおよびのインデックスを作成する方法 parent()
何らかのインデックスの親を決定する方法ですが、リストモデルがあるため、おそらく常に戻る必要があります QModelIndex()
. 。ここは カスタムモデルの作成に関する良い記事.
これが作業の完全な例です QAbstractListModel
:
class MyModel: public QAbstractListModel {
Q_OBJECT
public:
virtual QModelIndex index(int row, int column = 0,
const QModelIndex &parent = QModelIndex()) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void add(int i);
private:
QList<int> list;
};
void MyModel::add(int i)
{
beginInsertRows(QModelIndex(), list.size(), list.size());
list.append(i);
endInsertRows();
}
QModelIndex MyModel::index(int row, int column,
const QModelIndex &parent) const
{
return hasIndex(row, column, parent) ? createIndex(row, column, (void*)&list[row])
: QModelIndex();
}
int MyModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return list.size();
}
QVariant MyModel::data(const QModelIndex &index,
int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
return QVariant(QString::number(*static_cast<int*>(index.internalPointer())));
}
他のヒント
モデルインデックスにデータを処理するために必要なポインターが含まれているQabstractListModelを調理しました。
間違った要件から始めると、間違った解決策になります:)
a リスト モデルは十分にシンプルであるため、 QModelIndex
's row()
インデックスがアドレス指定するデータを一意に定義する。
だから、与えられた QModelIndex
mi
, 、あなたが以前にやったとき
PointItem * item = static_cast<PointItem*>(mi.internalPointer());
代わりにできる
PointItem * item = plm->pointItemFromIndex(mi);
どこ plm
あなたの PointListModel
. 。アクセスする必要があるときに横たわっているポインターがない場合 PointItem
, 、次のように再構築できます。
PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model());
// check for !plm here (!mi.isValid() || qobject_cast fails)
順番に、 PointListMode::pointItemFromIndex()
実際の仕事をするでしょう:
PointItem * PointListMode::pointItemFromindex(const QModelIndex &mi) const {
return mi.isValid() ? m_points[mi.row()] : 0 ;
}
これは、一緒に作業するときに実現する最も重要なことです QAbstractListModel
QT:精神的に置き換えます QModelIndex
と int row
, 、それが持っている他のすべてを無視します(無効です QModelIndex
もっている row() == -1
).
同じ QAbstractTableModel
: :精神的に減少します QModelIndex
に int row, int column
. 。他のすべてを忘れてください。
フルが必要な時間のみ QModelIndex
(それを含む internalPointer()
また internalId()
ツリーモデルを実装するときです(QAbstractItemModel
).