Hilfe zu QStandardItemModel bzw. QTreeView

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
mepi0011
Beiträge: 5
Registriert: 1. Juni 2010 08:43

Hilfe zu QStandardItemModel bzw. QTreeView

Beitrag von mepi0011 »

Hallo,

ich habe ein kleines Programm geschrieben, das mir Text-Dateien mit Messwerten konvertiert und daraus den minimal, maximal und Mittelwert berechnet. Dies Infos möchte ich nun in einer Tabelle und Baum darstellen.

Leider habe ich bereits mit dem Erstellen des QtreeView und dem QTableView meine Probleme. Hierzu habe ich versucht das Beispiel zu QtreeView (siehe QT Hilfe) umzusetzen.

Wenn ich das Programm ausführe, bleibt das Fenster leer.

Was mache ich falsch?

Header-Datei:

Code: Alles auswählen

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include <QTreeView>
#include <QTableView>
#include <QHBoxLayout>
#include <QStandardItemModel>
#include <QStandardItem>

QT_BEGIN_NAMESPACE
class QAbstractItemModel;
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QTreeView *tree;
    QTableView *table;
    QStandardItemModel treeModel;
    QStandardItemModel *tableModel;

};

#endif // MAINWINDOW_H

Programm:

Code: Alles auswählen

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QStandardItemModel treeModel;
    QStandardItem *parentItem = treeModel.invisibleRootItem();
     for (int i = 0; i < 4; ++i)
     {
         QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
         parentItem->appendRow(item);
         parentItem = item;
     }

    QStandardItemModel tableModel(4, 4);
    for (int row = 0; row < 4; ++row)
    {
        for (int column = 0; column < 4; ++column)
        {
            QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
            tableModel.setItem(row, column, item);
        }
    }

    QTreeView *tree = new QTreeView;
    QTableView *table = new QTableView;

    tree->setModel(&tableModel);
    table->setModel(&tableModel);

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addWidget(tree);
    mainLayout->addWidget(table);
    setLayout(mainLayout);
}

MainWindow::~MainWindow()
{

}
Dateianhänge
main.cpp
(187 Bytes) 193-mal heruntergeladen
mainwindow.cpp
(1.04 KiB) 182-mal heruntergeladen
mainwindow.h
(558 Bytes) 181-mal heruntergeladen
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Der Standardfehler schlechthin in letzter Zeit ;)
Du hast 2 "treeModel"s, eines ist der Member deiner Klasse, das andere ist ein lokales Objekt im Konstruktor, welches den Member überdeckt. Und das lokale überlebt den Konstruktor nicht :(
Verwende doch einfach den Member deiner Klasse.
kater
Beiträge: 306
Registriert: 29. Dezember 2009 01:13
Wohnort: Darmstadt

Beitrag von kater »

Spontan würde ich sagen, QStandardItemModel tableModel(4, 4); sollte ein Pointer sein und mit new erzeugt werden, damit die Variable überlegt wenn die ctor abgearbeitet ist.
mepi0011
Beiträge: 5
Registriert: 1. Juni 2010 08:43

Wie würde das mit dem Member aussehen?

Beitrag von mepi0011 »

Hallo franzf,

wie würde das mit dem Member meiner Klasse aussehen?

Kannst du mir ein Beispiel geben?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Wie würde das mit dem Member aussehen?

Beitrag von franzf »

mepi0011 hat geschrieben:wie würde das mit dem Member meiner Klasse aussehen?
Einfach kein neues Objekt im Konstruktor anlegen. Du hast doch in deiner "private"-section schon ein treeModel und ein tableModel (interessantertigerwese ein eines als Zeigertyp, das andere im automatischen Speicherbereich - gibt es da nen Grund?). Benutz doch die.
mepi0011
Beiträge: 5
Registriert: 1. Juni 2010 08:43

Programm auf das Wesentliche reduzierte (ohne Erfolg)

Beitrag von mepi0011 »

Hallo,

habe bereits verschiedene Varianten erfolglos ausprobiert, daher ist versehentlich ist das treeModel und tableModel in der private-Section unterschiedlich.
Leider bringt auch der folgende Code keine Ausgabe (leeres Fenster) :

Code: Alles auswählen

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QStandardItemModel *treeModel = new QStandardItemModel;
    QStandardItem *parentItem = new QStandardItem; //treeModel.invisibleRootItem();
     for (int i = 0; i < 5; ++i)
     {
         QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
         parentItem->appendRow(item);
         parentItem = item;
     }

    QStandardItemModel *tableModel= new QStandardItemModel; //(4, 4, this);
    tableModel->setColumnCount(4);
    tableModel->setRowCount(4);
    for (int row = 0; row < 4; ++row)
    {
        for (int column = 0; column < 4; ++column)
        {
            QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
            tableModel->setItem(row, column, item);
        }
    }

    QTreeView *tree = new QTreeView;
    QTableView *table = new QTableView;

    tree->setModel(treeModel);
    table->setModel(tableModel);

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addWidget(tree);
    mainLayout->addWidget(table);
    setLayout(mainLayout);
}
In der Zwischenzeit habe ich das Programm auf ein Minimum reduziert (siehe folgender Code). Dabei ist mir aufgefallen, dass mein eigentliches Problem (Tabelle wird nicht angezeigt) mit dem QHBoxLayout bzw. mit setCentralWidget(table) zusammenhängt.

Der folgende Code ist funktionsfähig:

Header-Datei:

Code: Alles auswählen

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include <QPushButton>

QT_BEGIN_NAMESPACE
class QAbstractItemModel;
class QAbstractItemView;
class QItemSelectionModel;
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QAbstractItemModel *model;
    QPushButton *button;

};

#endif // MAINWINDOW_H

Programm:

Code: Alles auswählen

#include "mainwindow.h"
#include <QtGui>
#include <QAbstractItemView>
#include <QItemSelectionModel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    model = new QStandardItemModel(8, 3);
    model->setHeaderData(0, Qt::Horizontal, tr("Label"));
    model->setHeaderData(1, Qt::Horizontal, tr("min"));
    model->setHeaderData(2, Qt::Horizontal, tr("max"));

    QTableView *table = new QTableView;
    table->setModel(model);

    setCentralWidget(table);

    /*
    QPushButton *button = new QPushButton("Hallo",this);
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(table);
    mainLayout->addWidget(button);
    setLayout(mainLayout);
    */
}

MainWindow::~MainWindow()
{

}
Wenn ich den Code wie folgt ändere, wird die Tabelle nicht angezeigt! Warum? Was mache ich Falsch?

Code: Alles auswählen

#include "mainwindow.h"
#include <QtGui>
#include <QAbstractItemView>
#include <QItemSelectionModel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    model = new QStandardItemModel(8, 3);
    model->setHeaderData(0, Qt::Horizontal, tr("Label"));
    model->setHeaderData(1, Qt::Horizontal, tr("min"));
    model->setHeaderData(2, Qt::Horizontal, tr("max"));

    QTableView *table = new QTableView;
    table->setModel(model);

    //setCentralWidget(table);

    //QPushButton *button = new QPushButton("Hallo",this);
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(table);
    //mainLayout->addWidget(button);
    setLayout(mainLayout);

}

MainWindow::~MainWindow()
{

}
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

QMainWindow verwendet ein eigenes Layout. Der Versuch, ein neues Layout zu setzen, resultiert in einer Meldung auf der Console:

Code: Alles auswählen

QWidget::setLayout: Attempting to set QLayout "" on QWidget "", which already has a layout
Ergo: geht nicht ;)
QMainWindow braucht das layout, um die ganzen Sachen wie toolbars, dockwidgets, etc. im Fenster anzuordnen. Der eigentliche Inhalt kommt in das centralWidget.

BTW.: Wenn du ein QStandardItemModel verwendest, willst (musst!) du auch dessen Interface nutzen, um Items hinzuzufügen. Da macht es gar keinen Sinn, das model nur über nen Basisklassenzeiger auf QAbstractItemModel als Member zu speichern. Wenn du keinen guten Grund hast (z.B. zur Laufzeit das Model vom ItemModel auf SqlTableModel oder so) zu ändern, nimm doch direkt ein QStandardItemModel*. Spart dir unnötige casts bei den Zugriffen :)
mepi0011
Beiträge: 5
Registriert: 1. Juni 2010 08:43

Auszüge aus Chart Example

Beitrag von mepi0011 »

Hallo franzf,

Teile des letzten Code sind aus dem Beispiel "Chart Example", daher auch das

Code: Alles auswählen

QAbstractItemModel *model;
in der Header-Datei.

Abhängig davon ob ich

Code: Alles auswählen

setCentralWidget(table);
oder

Code: Alles auswählen

QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(table);
    setLayout(mainLayout);
verwende, erhalte ich verschiedene Ergebnisse (siehe angefügte Bilder).

Wie muss ich das Beispiel ändern, dass es auch mit den QVBoxLayout funktioniert? (am besten als Code).
Dateianhänge
mit<br />QVBoxLayout *mainLayout = new QVBoxLayout;<br />    mainLayout-&amp;gt;addWidget(table);<br />    setLayout(mainLayout);
mit
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout-&gt;addWidget(table);
setLayout(mainLayout);
BoxLayout.PNG (6.06 KiB) 6490 mal betrachtet
mit<br />setCentralWidget(table);
mit
setCentralWidget(table);
mainLayout.PNG (11.22 KiB) 6490 mal betrachtet
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Indem du ein eigenes QWidget nimmst, diesem das Layout zuweist, und das als centralWidget setzt?

Code: Alles auswählen

QVBoxLayout* l = new QVBoxLayout;
l->addWidget( table );
QWidget* cw = new QWidget;
cw->setLayout( l );
setCentralWidget( cw );
Antworten