Model View Tutorial Part1/de

From Qt Wiki
Jump to navigation Jump to search
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine.
Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean.

← Allgemeines: Klasse CdRack
↑Übersicht Model/View Tutorial:CD Verwaltung↑
Teil 2: Editieren von Werten→

Ein read only (Table) Model

In unserem Beispiel leiten wir die Model Klasse von der allgemeinsten Basisklasse für Modelle ab, von QAbstractItemModel [doc.qt.nokia.com]. QAbstractItemModel bietet für viele Funktionen (z.B. alle die zum Editieren benötigt werden) Standard-Implementierungen.

Die folgenden Methoden sind abstrakt und müssen auf jeden Fall überschrieben (und implementiert) werden:

  1.   virtual int rowCount(const QModelIndex &parent = QModelIndex()) const =0;
  2.   virtual int columnCount(const QModelIndex &parent = QModelIndex()) const =0;
  3.   virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) =0;
  4.   virtual QModelIndex parent(const QModelIndex &child) const =0;
  5.   virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const =0;

Im folgenden werden die Methoden und ihre Implementierungen beschrieben

rowCount

Die Methode rowCount liefert die Anzahl der Zeilen (ohne die Überschrift). In unserem Beispiel ist es einfach die Anzahl der CDs in der Liste. (Wie in C++ üblich hat die erste Spalte den Index 0.)

  1. int CdModel::rowCount(const QModelIndex &parent) const
  2. {
  3.     return m_data.size();
  4. }

columnCount

Die Methode columnCount liefert die Anzahl der Spalten. In unserem Beispiel ist die Anzahl der Spalten fest, aber die Spaltenüberschriften sind einer QStringList gespeichert. (Wie in C++ üblich hat die erste Spalte den Index 0.)

  1. int CdModel::columnCount(const QModelIndex &parent) const
  2. {
  3.     if(!parent.isValid())
  4.         return 0;
  5.  
  6.     return m_columns.count();
  7. }

parent

Die Methode parent wird für hierarchische Modelle benötigt. In unserem Beispiel liefern wir immer einen ungültigen Modell-Index. Damit erreichen wir, dass alle Elemente in einer Ebene liegen.

  1. QModelIndex CdModel::parent(const QModelIndex &child) const
  2. {
  3.     return QModelIndex();
  4. }

data

Die Methode data gibt die anzuzeigenden Daten zurück. Die Daten sind als QVariant typisiert. Dies ist notwendig, da sie auch für Farben und ähnliches brauchbar sein muss. Mittels des Parameters role sagt die View, wofür sie die Daten braucht. Es wird ein Wert aus Qt::ItemDataRole [doc.qt.nokia.com] übergeben. In unserem Beispiel kümmern wir uns nur um den Wert Qt::DisplayRole. Dieser wird verwendet, um Daten abzufragen, die als Hauptanzeige-Daten dienen (nicht Farbe, Schriftart, etc.), also bei uns die anzuzeigenden Texte. Es könnten aber auch Bilder (z.B. CD-Covers) sein.

  1. QVariant CdModel::data(const QModelIndex &index, int role) const
  2. {
  3.     if(!index.isValid())
  4.         return QVariant();
  5.  
  6.     if(Qt::DisplayRole == role)
  7.     {
  8.         const CdDisk& rDisk = m_data.at(index.row());
  9.         switch(index.column())
  10.         {
  11.         case 0:
  12.             return rDisk.m_title;
  13.         case 1:
  14.             return rDisk.m_author;
  15.         case 2:
  16.             return rDisk.m_genre;
  17.         case 3:
  18.             return rDisk.m_year;
  19.         }
  20.     }
  21.  
  22.     return QVariant();
  23. }

Die am meisten genutzten Werte für den Parameter role sind (In Klammern der Datentyp, der zurückgegeben wird):

Werte Bedeutung
Qt::DisplayRole Hauptdaten, werden in Textform dargestellt. (QString)
Qt::DecorationRole Daten, die in Form eines Icons (üblicherweise vor den Hauptdaten) angezeigt werden sollen. (QColor, QIcon oder QPixmap)
Qt::EditRole Hauptdaten, allerdings so aufbereitet, das sie in einem Editor geändert werden können. (QString)
Qt::BackgroundRole Hintergrund, der vom benutzt wird, wenn das Element gerendert wird. (QBrush)
Qt::ForegroundRole Vordergrund (typischerweise die Textfarbe) die benutzt werden soll. (QBrush)
Qt::CheckStateRole Diese Rolle wird verwendet, um ein Kontrollkästchen vor dem Element anzuzeigen. (Qt::CheckState)
Qt::UserRole Mit Werten größer oder gleich diesem Wert können anwendungsspezifische Daten hinterlegt werden.

DisplayRole und EditRole können unterschiedliche Datentypen zurückliefern, z.B. wenn ein QDate angezeigt werden soll, kann bei DisplayRole das Datum bereits in einen Text gerendert werden und bei EditRole als QDate zurückgeliefert werden. Das hat zur Folge, das die Standard Implementierung ein QDateEdit zum Editieren benutzt, und kein QLineEdit.

index

Die Methode index wird verwendet, um aus einer Zeile und einer Spalte (und bei hierarchischen Modellen dem Parent) ein gültiges QMOdelIndex-Objekt zu erzeugen. Bei komplexen (oder sehr großen) Datenmengen kann in dem QModelIndex-Objekt noch zusätzliche Informationen abgelegt werden (z.B. ein Pointer auf ein Objekt). Diese Informationen dürfen nur vom Modell ausgewertet werden.

  1. QModelIndex CdModel::index(int row, int column, const QModelIndex &parent) const
  2. {
  3.     if(parent.isValid())
  4.         return QModelIndex();
  5.  
  6.     if( (0 <= row) && (row < rowCount()) &&
  7.         (0 <= column) && (column < columnCount()))
  8.     {
  9.         return createIndex(row, column);
  10.     }
  11.     return QModelIndex();
  12. }

headerData

Die Methode headerData muss zwar nicht zwingend überschrieben werden, wird aber benötigt, wenn eine Überschrift angezeigt werden soll, die nicht aus der Spaltennummer besteht. Sinnvollerweise sollte index (section) immer auf Gültigkeit überprüft werden. Wie bei data gibt es den Parameter role. Zusätzlich gibt es orientation. Dieser Parameter wird genutzt, um zwischen horizontalem und vertikalem Header zu unterscheiden.

  1. QVariant CdModel::headerData(int section, Qt::Orientation orientation, int role) const
  2. {
  3.     if( (Qt::DisplayRole == role) &&
  4.         (Qt::Horizontal == orientation) &&
  5.         (0 <= section) &&
  6.         (section < columnCount()))
  7.     {
  8.         return m_columns.at(section);
  9.     }
  10.     return QVariant();
  11. }

Code für die Beispielapplikation als zip Datei zum Download [docs.google.com]