Wie assoziieren Sie QModelIndex mit einer neuen Zeile?
-
25-10-2019 - |
Frage
Ich habe a gekocht a QAbstractListModel
Wessen Modellindizes enthalten einen Zeiger, den ich unbedingt benötigte, um Daten zu verarbeiten. Ich füge die Daten wie SO hinzu:
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 );
}
Erst später wurde mir klar, dass das Argument zu beginInsertRows
fragt nach dem Elternteil Modellindex der neuen Zeile, nicht der tatsächliche Modellindex der neuen Zeile.
Zu diesem Zeitpunkt hat QT mir keine Möglichkeit gegeben, a zu liefern QModelIndex
mit dieser speziellen Reihe zu verknüpfen. Wie erstelle ich meinen eigenen Modellindex für diese neue Zeile?
Lösung
Okay, ich schreibe meine Antwort neu, da ich nach einigen Nachforschungen herausgefunden habe, dass ich es falsch verstanden habe.
Sie sollten nichts Besonderes tun, um einen neuen Index zu erstellen, wenn Sie neue Daten hinzufügen. Ihr Code sollte so aussehen:
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();
Dann sollten Sie die implementieren index()
Methode, die Indizes bei Bedarf erzeugt und die parent()
Methode, die den übergeordneten Index bestimmt, aber da Sie ein Listenmodell haben, sollte es wahrscheinlich immer nur zurückkehren QModelIndex()
. Hier ist Ein guter Artikel über das Erstellen benutzerdefinierter Modelle.
Hier ist ein vollständiges Beispiel für eine Arbeit 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())));
}
Andere Tipps
Ich habe ein QabstractListModel gekocht, dessen Modellindizes einen Zeiger enthalten, den ich unbedingt benötigte, um Daten zu verarbeiten.
Wenn Sie mit falschen Anforderungen beginnen, erhalten Sie falsche Lösungen :)
EIN aufführen Modell ist einfach genug, damit Sie nicht mehr als die benötigen QModelIndex
's row()
So definieren Sie die Daten, die die Index ansprechen.
Also gegeben a QModelIndex
mi
, als Sie zuvor getan haben
PointItem * item = static_cast<PointItem*>(mi.internalPointer());
Sie können stattdessen tun
PointItem * item = plm->pointItemFromIndex(mi);
wo plm
ist dein PointListModel
. Wenn Sie keinen Zeiger haben, der herumliegt, wenn Sie auf die zugreifen müssen PointItem
, Sie können es so rekonstruieren:
PointItemModel * plm = qobject_cast<PointItemModel*>(mi.model());
// check for !plm here (!mi.isValid() || qobject_cast fails)
Im Gegenzug, PointListMode::pointItemFromIndex()
würde die tatsächliche Arbeit erledigen:
PointItem * PointListMode::pointItemFromindex(const QModelIndex &mi) const {
return mi.isValid() ? m_points[mi.row()] : 0 ;
}
Dies ist das Wichtigste, was man bei der Arbeit mit der Arbeit erkennen kann QAbstractListModel
in QT: Mental ersetzen QModelIndex
mit int row
, ignorieren Sie alles andere, was es hat (einen Invalid QModelIndex
hat row() == -1
).
Gleiches für QAbstractTableModel
: reduzieren die mental die QModelIndex
zu int row, int column
. Vergiss alles andere.
Das einzige Mal, dass Sie das volle benötigen QModelIndex
(einschließlich dessen internalPointer()
oder internalId()
ist, wenn Sie ein Baummodell implementieren (QAbstractItemModel
).