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 srow()即可唯一地定义索引地址的数据。

所以,给定一个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:精神上减少QModelIndexint row, int column。忘记其他一切。

唯一需要完整的时候QModelIndex(包括它的internalPointer()orinternalId()是在实现树模型 ( ) 时QAbstractItemModel)。

于 2012-06-24T08:34:07.520 回答