[gelöst] Delegate/View/Table

Alles rund um die Programmierung mit Qt
Antworten
tamasi
Beiträge: 45
Registriert: 5. Juli 2007 15:49

[gelöst] Delegate/View/Table

Beitrag von tamasi »

Hi

Ich bin erst seit 3 Wochen an QT dran und soll von der Arbeit aus ein Projekt umsetzen.

Hierbei handelt es sich um ein UI, unter anderem mit einer Tabelle.

Die Tabelle befindet sich in einem Splitter und wird als

Code: Alles auswählen

tabelle = new QTableView();
deklariert.( in Datei a1)
In der Tabelle werden in den ersten beiden Spalten Strings angezeigt und die restlichen Spalten(dynamisch) werden mit Int Werten gefüllt.

Dazu habe ich ein Modell generiert( in Datei a2) und die üblichen Funktionen überschrieben.(wie in den Doku-Beispielen gezeigt)

Code: Alles auswählen

class cTableModel : public QAbstractTableModel
{
public:
  cTableModel(QString filename,QObject *parent = 0);
  int rowCount(const QModelIndex &parent) const;
  int columnCount(const QModelIndex &parent) const;
  QVariant data(const QModelIndex &index, int role) const;
  bool setData(const QModelIndex &index, const QVariant &value, int role);
  QVariant headerData(int section, Qt::Orientation, int role) const;
  QStringList* qsl1;
  QStringList* qsl2;
  QList<QString> ql1;
  QList<QString> ql2;
  QList<QString> ql3;
  QVector<int> iVector;
In ql1 stehen die String der ersten beiden Spalten und in iVector die Int-Zahlen.

Soweit so gut.
Damit wird das File ausgelesen,und die Tabelle wird korrekt angezeigt.

Zusätzlich sollen jetzt die Int-Werte vom Benutzer Editierbar sein, die Strings nicht.

Dazu wieder in der Doku gelesen und ein Delegate gebastelt(Datei a3).
Das SpinBox Beispiel ist eig schon fast dass, was ich möchte.

Code: Alles auswählen

class cItemDelegate : public QItemDelegate {
    Q_OBJECT

 public:
     cItemDelegate(QObject *parent = 0);

     QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                           const QModelIndex &index) const;

     void setEditorData(QWidget *editor, const QModelIndex &index) const;
     void setModelData(QWidget *editor, QAbstractItemModel *model,
                       const QModelIndex &index) const;

     void updateEditorGeometry(QWidget *editor,
         const QStyleOptionViewItem &option, const QModelIndex &index) const;
 };
Mein Problem ist jetzt, aktiviere ich den Delegate (in datei a1 nach der Deklaration von meinem QTableView

Code: Alles auswählen

w2QTV1 = new QTableView();
  cTM = new cTableModel();
  w2QTV1->setModel(cTM);
  cItemDelegate* delegate = new cItemDelegate(this);
  w2QTV1->setItemDelegate(delegate);
verschwindet der Inhalt meine Tabelle völlig. Weit und breit keine Spur von den Daten oder gar einer SpinBox.

In der Firme machte jemand schon etwas ähnliches mit einer Datenbank.
Dazu implementierte derjenige auch einen Ableitung von QTableView-> cTableView.
Mir liegen leider nur teilweise die Dateien vor, aber logischerweise müsste dann auch

Code: Alles auswählen

tabelle = new QTableView();

im Konstruktor in Datei a1 stehen.

Muss ich das auch machen, und wenn ja, was müsste dort ca rein oder ist mein Fehler ganz woanders?
Sehe zur Zeit den Wald vor lauter Bäumen nicht:(.
Zuletzt geändert von tamasi am 6. Juli 2007 12:44, insgesamt 1-mal geändert.
tamasi
Beiträge: 45
Registriert: 5. Juli 2007 15:49

Beitrag von tamasi »

Ich glaube, ich konnte mein Anliegen nicht so recht rüberbringen. Mir geht es nicht um eine Lösung, voila, reinkopieren fertig, sondern eher um Aufklärung. Man will ja was lernen:).

Was muss genau wo rein?Ich habe zum Teil noch das Problem, welcher Teil der Model/View Architektur nun mit welchen eig in Kontakt steht, also wo rufe ich das Model den Delegat usw genau auf.

ich habe meine Datei a0-->main mit QApplication und show().

dann Datei a1-->Konstruktor für mein Gui, inkl Tabelle mit tabelle=QTableView.

dann Datei a2-->cTableModel mit data+setdata, header usw, alles was das Model braucht

dann datei a3-->der Delegate, bisher fast 1 zu 1 aus SpinBox Beispiel kopiert

Funktioniert die Modelunterteilung in String und Vector für die Tabelle später so wie sie soll?
Brauche ich eine Datei a4 als Ableitung von QTableView und wenn ja, was muss in die Datei?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Vergiss vorerst mal das Delegate, da du nur mit Strings und Zahlen arbeitest, reicht im ersten Moment das, was Qt vorgibt.

Anschließend nimmst du deine View und weist ihr dein Model zu.

Im Model entscheidest du anhand der Flags, ob eine Zelle editierbar ist oder nicht.

Code: Alles auswählen

Qt::ItemFlags QAbstractItemModel::flags ( const QModelIndex & index ) const 
In der Funktion

Code: Alles auswählen

QVariant QAbstractItemModel::data ( const QModelIndex & index, int role = Qt::DisplayRole ) const
lieferst du die sichtbaren Daten für die EditRole und die DisplayRole zurück.

Bei

Code: Alles auswählen

bool QAbstractItemModel::setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ) 
brauchst du dann nur die EditRole beachten.

Im übrigen hast du es leichter wenn du für jede Tabellenzeile dir eine Struktur definierst und diese dann in eine QList packst. Verwaltet sich leichter.

Code: Alles auswählen

struct MyData {
  QString qsl1;
  QString qsl2;
  QVector<int> iVector;
}

QList<MyData> m_data;
tamasi
Beiträge: 45
Registriert: 5. Juli 2007 15:49

Beitrag von tamasi »

Die Idee mit der Struktur ist gut, werde ich gleich umsetzen. Meine Speicherung war etwas komplizierter:).

Um ein Delegate werde ich leider nicht herum kommen. Eine SpinBox über den Int-Werten ist vertraglich vereinbart.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Es ging mir nicht darum, daß du das komplett Delegate wegläst, sondern erst mal ohne Delegate arbeitest, bis das Model richtig funktioniert. Danach kannst du dich dann wieder auf das Delegate konzentrieren.
tamasi
Beiträge: 45
Registriert: 5. Juli 2007 15:49

Beitrag von tamasi »

Ich denke das Model funktioniert eig. Ob alles 100% korrekt ist kann ich nicht mit Sicherheit sagen. Aber ohne Delegate werden mir alle Header richtig angezeigt, die Tabelle richtig befüllt, die Spalten die bearbeitet werden sollen, können zumindest angeklickt werden. Ist eig so, wie es sein soll.
Mit deinen Tips habe ich noch die Teile der Tabelle als modelliert, die nicht verändert werden dürfen.

Was für meine Begriffe jetzt noch fehlt ist halt der Delegate, der beim Doppelklick auf einen der Int Werte die SpinBox öffnet.

Zumindest konnte ich durch kleiner Ändrungen ersteinmal nach Aktivierung meines Delegates mit die Tabellendaten erhalten.

Code: Alles auswählen

cItemDelegate* delegate = new cItemDelegate(w2QTV1);
  w2QTV1->setItemDelegate(delegate);
Aber irgendwas scheint wohl am Delegate nicht so ganz zu stimmen.

Code: Alles auswählen

#include "stdafx.h"
#include <QtGui>
#include "moc_cItemDelegate.cpp"

cItemDelegate::cItemDelegate(QObject *parent)
     : QItemDelegate(parent)
 {
 }


QWidget *cItemDelegate::createEditor(QWidget *parent,
     const QStyleOptionViewItem & option ,
     const QModelIndex & index ) const
 {
   if (index.column()==0 || index.column()==1) {
     return parent;
   }
   else if (index.column()>=2) {
     QSpinBox *editor = new QSpinBox(parent);
     editor->setMinimum(0);
     return editor;
   }
   else {
     return QItemDelegate::createEditor(parent,option,index);
   }
 }

void cItemDelegate::setEditorData(QWidget *editor,
                                     const QModelIndex &index) const {
     if (!(index.column()==0 || index.column()==1)) {
        int value = index.model()->data(index, Qt::DisplayRole).toInt();
        QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
        spinBox->setValue(value);
     }
 }

void cItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                    const QModelIndex &index) const
 {   if (!(index.column()==0 || index.column()==1)) {
       QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
       spinBox->interpretText();
       int value = spinBox->value();
       model->setData(index, value);
}
 }

void cItemDelegate::updateEditorGeometry(QWidget *editor,
     const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
 {
     editor->setGeometry(option.rect);
 }
void cItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const {
  if (!(index.column()==0 || index.column()==1)) {
    QString value = index.model()->data(index, Qt::DisplayRole).toString();
    QStyleOptionViewItem myOption = option;
    myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;

    drawDisplay(painter, myOption, myOption.rect, value);
    drawFocus(painter, myOption, myOption.rect);
  } 
  else{
    QItemDelegate::paint(painter, option, index);
  }
}
tamasi
Beiträge: 45
Registriert: 5. Juli 2007 15:49

Beitrag von tamasi »

habs, setzte das flag beim befüllen nicht richtig deshalb war kein iseditabel flag drin, ergo nix spinbox

so ein doofer fehler, hält fast 1 tag auf, nerv.

noch übernimmt er den neuen wert nicht richtig, aber das wurschtel ich mir auch noch hin.

danke für die hilfe.
Antworten