7

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、この特定の行に関連付ける を提供する方法を私に与えていません。この新しい行に独自のモデル インデックスを作成するにはどうすればよいですか?

4

2 に答える 2

6

さて、いくつかの調査の結果、間違っていることがわかったので、回答を書き直しています。

新しいデータを追加するときに、新しいインデックスを作成するために特別なことを行うべきではありません。コードは次のようになります。

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())));
}
于 2011-01-27T07:01:51.047 に答える
2

データを処理するために絶対に必要なポインターをモデル インデックスに含む QAbstractListModel を作成しました。

間違った要件から始めると、間違ったソリューションになってしまいます :)

リストモデルは十分に単純であるため、インデックスがアドレス指定するデータを一意に定義するために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 ;
}

これは、Qt で作業するときに実現する最も重要なことですQAbstractListModel。精神的に に置き換えQModelIndexint row他のすべてを無視します (無効なQModelIndexhas row() == -1)。

についても同じですQAbstractTableModel: 精神的に を に減らしQModelIndexますint row, int column。他のすべてを忘れてください。

フルQModelIndex(internalPointer()またはを含む) が必要になるのinternalId()は、ツリー モデル ( ) を実装するときだけですQAbstractItemModel

于 2012-06-24T08:34:07.520 に答える