Qt 如何将QModelIndex与新行关联?

Qt 如何将QModelIndex与新行关联?,qt,qmodelindex,qabstractlistmodel,Qt,Qmodelindex,Qabstractlistmodel,我制作了一个QAbstractListModel,它的模型索引包含一个我处理数据绝对需要的指针。我添加如下数据: void PointListModel::addPoint(int frameNumber, QPoint const& pos) { PointItem *pointItem = new PointItem( frameNumber, pos ); QModelIndex newRow = this->createIndex( m_points.cou

我制作了一个
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 );
}
void PointListModel::addPoint(int frameNumber,QPoint const&pos)
{
PointItem*PointItem=新的PointItem(帧号,位置);
QModelIndex newRow=this->createIndex(m_points.count(),0,pointItem);

qDebug()好的,我正在重写我的答案,因为经过一些研究,我发现我错了

添加新数据时,不应执行任何特殊操作来创建新索引。代码应如下所示:

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();
PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model());
// check for !plm here (!mi.isValid() || qobject_cast fails)
然后您应该实现
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())));
}
classmymodel:publicqabstractlistmodel{
Q_对象
公众:
虚拟QModelIndex索引(int行,int列=0,
常量QModelIndex&parent=QModelIndex())常量;
虚拟整数行计数(常量QModelIndex&parent=QModelIndex())常量;
虚拟QVariant数据(常量QModelIndex&index,int-role=Qt::DisplayRole)常量;
无效添加(int i);
私人:
QList列表;
};
void MyModel::add(int i)
{
beginInsertRows(QModelIndex(),list.size(),list.size());
列表。附加(i);
endInsertRows();
}
QModelIndex MyModel::index(int行,int列,
常数QModelIndex和父项)常数
{
return hasIndex(行、列、父项)?createIndex(行、列、(void*)和list[row])
:QModelIndex();
}
int MyModel::行计数(常量QModelIndex&parent)常量
{
if(parent.isValid())
返回0;
返回list.size();
}
QVariant MyModel::数据(常量QModelIndex和索引,
int角色)常量
{
如果(!index.isValid())
返回QVariant();
if(角色!=Qt::DisplayRole)
返回QVariant();
返回QVariant(QString::number(*static_cast(index.internalPointer()));
}
我制作了一个QAbstractListModel,它的模型索引包含一个指针,我绝对需要它来处理数据

如果您从错误的需求开始,那么最终会得到错误的解决方案:)

列表模型非常简单,因此只需要
QModelIndex
row()
就可以唯一地定义索引地址的数据

因此,当您之前使用了一个
QModelIndex
mi

PointItem * item = static_cast<PointItem*>(mi.internalPointer());
其中,
plm
是您的
PointListModel
。如果您需要访问
PointItem
时没有指向它的指针,您可以这样重新构建它:

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();
PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model());
// check for !plm here (!mi.isValid() || qobject_cast fails)
这是在Qt中使用
QAbstractListModel
时要意识到的最重要的一点:用
int row
替换
QModelIndex
,忽略它拥有的所有其他内容(无效的
QModelIndex
拥有
row()=-1

同样适用于
QAbstractTableModel
:将
QModelIndex
精神上减少为
int行,int列
。忘掉其他一切


唯一需要完整的
QModelIndex
(包括它的
internalPointer()
internalId()
)的时候是在实现树模型(
qabstractemmodel
)的时候。这看起来越来越接近我想要的,但据我所知,索引()函数不是专门为创建新行而调用的。我如何区分新行和现有行之间的index()调用?我有一个QMap存储我的数据,但QMap键目前不是按行号进行的。@nessup,默认的QAbstractListModel::index()实现总是调用createIndex()对于任何有效的坐标,我猜它应该为每个调用创建一个新的索引,尽管这对我来说似乎也很奇怪。也许索引创建操作被认为是便宜的,所以创建多个重复的索引是完全可以的。毕竟,您的实现将与默认的实现相同,只是您传递的不同一些有意义的东西,比如指向createIndex()的数据指针,而不是NULL(默认实现是这样)。好的,谢谢。我将尝试在代码中保留一个QMap,如果QMap在给定行中不包含适当的QModelIndex,则返回一个新的QModelIndex。我会告诉您它是如何运行的。嘿——看起来像index()从未在data()之前调用过,然后QModelIndex的内部指针为零:/@nessup,好的,我也会尝试测试它并发布结果。但我真的认为没有必要使用映射。