I create a simple QMainWindow app as follows:
The header file:
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QAbstractItemModel>
#include <QTreeView>
#include <QVBoxLayout>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MyTreeModel : public QAbstractItemModel
{
public:
Q_OBJECT
public:
MyTreeModel(QObject *parent=NULL);
QModelIndex parent(const QModelIndex &index) const;
QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation,int role = Qt::DisplayRole) const;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QTreeView * view;
MyTreeModel *model;
private:
Ui::MainWindow *ui;
QVBoxLayout * layout;
};
#endif // MAINWINDOW_H
The source file:
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
QModelIndex MyTreeModel::parent(const QModelIndex &index) const
{
return QModelIndex();
}
QVariant MyTreeModel::data(const QModelIndex &index, int role) const
{
return "111";
}
QVariant MyTreeModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
if(section==0)
return "Column0";
else if(section==1)
return "Column1";
else if(section==2)
return "Column2";
else
return QVariant();
}
else
return QVariant();
}
QModelIndex MyTreeModel::index(int row, int column, const QModelIndex &parent)
const
{
return createIndex(row, column, NULL);
}
int MyTreeModel::columnCount(const QModelIndex &parent) const
{
return 3;
}
int MyTreeModel::rowCount(const QModelIndex &parent) const
{
return 2;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
model=new MyTreeModel();
view= new QTreeView(this);
view->setModel(model);
layout= new QVBoxLayout(this);
layout->addWidget(view);
QWidget *window = new QWidget();
window->setLayout(layout);
setCentralWidget(window);
}
MainWindow::~MainWindow()
{
delete ui;
}
I expect it will show a 2 rows * 3 columns of "111", but it does not. It only shows the header. If I change QVariant MyTreeModel::headerData
to:
QVariant MyTreeModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if(section==0)
return "Column0";
else if(section==1)
return "Column1";
else if(section==2)
return "Column2";
else
return QVariant();
}
It will show nothing. The header also disappears.
Why?
Your code a has a couple of issues. Firstly, because it's a single level model the index
, rowCount
and columnCount
members should only return 'real' values when the specified parent index is invalid (i.e. the nominal root index). So those members become...
QModelIndex MyTreeModel::index (int row, int column, const QModelIndex &parent) const
{
if (parent.isValid())
return {};
return createIndex(row, column, nullptr);
}
int MyTreeModel::columnCount (const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return 3;
}
int MyTreeModel::rowCount (const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return 2;
}
Secondly, your MyTreeModel::data
member always returns (effectively) QString("111")
. That will fail for those roles where a QString
can't be converted to the expected type: e.g. QSize
for Qt::SizeHintRole
. So the data
member becomes...
QVariant MyTreeModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole)
return {};
return "111";
}
With the above changes the code appears to work as expected.