我已经制作了一个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
与此特定行相关联。如何为这个新行创建自己的模型索引?
答案 0 :(得分: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()
。这是a good article about creating custom models。
以下是工作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())));
}
答案 1 :(得分:2)
我已经制作了一个QAbstractListModel,其模型索引包含一个我绝对需要的指针来处理数据。
如果您从错误的要求开始,最终会得到错误的解决方案:)
list 模型非常简单,因此您不需要超过QModelIndex
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
时,这是最重要的事情:用QModelIndex
精神取代int row
,忽略它拥有的所有内容(无效的QModelIndex
具有row() == -1
QAbstractTableModel
)。
QModelIndex
相同:从精神上将int row, int column
缩减为QModelIndex
。忘记其他一切。
当您实施树模型(internalPointer()
)时,唯一需要完整internalId()
(包括其QAbstractItemModel
或{{1}}的时间。