Come associare QModelIndex con una nuova riga?
-
25-10-2019 - |
Domanda
Ho cucinato un QAbstractListModel
cui indici modello contenere un puntatore Sono assolutamente necessario al fine di elaborare i dati. Aggiungo i dati in questo modo:
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 );
}
E 'stato solo più tardi che mi sono reso conto che l'argomento a beginInsertRows
sta chiedendo per il genitori Indice di modello della nuova riga, non indice di modello reale della nuova riga.
Quindi, a questo punto nel tempo, Qt mi ha dato modo di fornire un QModelIndex
da associare a questa particolare riga. Come faccio a creare il mio indice di modello di questa nuova riga?
Soluzione
Va bene, sto riscrivendo la mia risposta come dopo alcune ricerche ho scoperto che mi sono sbagliato.
Non si dovrebbe fare nulla di speciale per creare un nuovo indice quando si aggiungono nuovi dati. Si codice dovrebbe essere simile a questo:
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();
Poi si dovrebbe implementare il metodo index()
che creerà indici su richiesta e il metodo parent()
che determinerà il genitore di qualche indice, ma dal momento che si dispone di un modello di lista, si dovrebbe probabilmente sempre e solo tornare QModelIndex()
. Ecco un buon articolo sulla creazione di modelli personalizzati .
Ecco un esempio completo di un QAbstractListModel
di lavoro:
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())));
}
Altri suggerimenti
Ho cucinato un QAbstractListModel cui indici modello contenere un puntatore Sono assolutamente necessario al fine di elaborare i dati.
Se si inizia con i requisiti sbagliate, si finisce con soluzioni sbagliate:)
A modello è abbastanza semplice in modo che non avete bisogno di più di QModelIndex
del row()
per definire i dati in modo univoco gli indirizzi di indice.
Quindi, dato un QModelIndex
mi
, quando prima di fatto
PointItem * item = static_cast<PointItem*>(mi.internalPointer());
si può invece fare
PointItem * item = plm->pointItemFromIndex(mi);
dove è il vostro plm
PointListModel
. Se non si dispone di un puntatore ad esso in giro quando è necessario accedere al PointItem
, è possibile ricostruire in questo modo:
PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model());
// check for !plm here (!mi.isValid() || qobject_cast fails)
A sua volta, PointListMode::pointItemFromIndex()
farebbe il lavoro effettivo:
PointItem * PointListMode::pointItemFromindex(const QModelIndex &mi) const {
return mi.isValid() ? m_points[mi.row()] : 0 ;
}
Questa è la cosa più importante da capire quando si lavora con QAbstractListModel
in Qt:. Mentalmente sostituire QModelIndex
con int row
, ignora tutto il resto è (un QModelIndex
invalido ha row() == -1
)
Lo stesso per QAbstractTableModel
: ridurre mentalmente il QModelIndex
a int row, int column
. Dimenticate tutto il resto.
L'unica volta che è necessario il pieno QModelIndex
(compresa la sua internalPointer()
o internalId()
è quando si implementa un modello ad albero (QAbstractItemModel
).