5

How can I implement this code I have for a qTreeWidget for a qTreeView?

for (const auto & i : names) {
    QTreeWidgetItem * item = new QTreeWidgetItem(ui->treeWidget);
    item->setText(0, QString::fromStdString(i));
    ui->treeWidget->addTopLevelItem(item);
    const std::unordered_map<std::string, double> map = m_reader.getMapFromEntry(i);
    for (const auto & j : map) {
        QTreeWidgetItem * item2 = new QTreeWidgetItem();
        item2->setText(0,QString::fromStdString(j.first));
        item2->setText(1,QString::number(j.second));
        item->addChild(item2);
    }

}

I have a model and a treeView, like this:

m_model = new QStandardItemModel(m_reader.getAllNames().size(),2,this);
ui->treeView->setModel(m_model);

I tried this, but that only shows one column:

QStandardItem * parentItem = m_model->invisibleRootItem();
for (const auto & i : names) {
    QStandardItem * item = new QStandardItem(QString::fromStdString(i));
    parentItem->appendRow(item);
    const std::unordered_map<std::string, double> map = m_reader.getMapFromEntry(i);
    for (const auto & j : map) {
        QList<QStandardItem *> rowItems;
        rowItems << new QStandardItem(QString::fromStdString(j.first));
        rowItems << new QStandardItem(QString::number(j.second));
        item->appendRow(rowItems);
    }
}

With the treeWidget, I had so set the columnCount, like this:

ui->treeWidget->setColumnCount(2);

But treeView does not have a method like this.

So, to summarize: How can I implement a TreeView with more than one column?

EDIT:
To clarify, I want something like this:

|-A
| |-B-C
| |-D-E

where A is the parent and B,C,D,E the children, with B,D being in column 0 and C,E in column 1.

Hope this helps!

gartenriese
  • 4,131
  • 6
  • 36
  • 60

2 Answers2

7

To support multiple columns, the model must contain data for multiple columns. So in some sense, columns are a property of the model, not the view. Views then can decide to hide or rearrange certain columns (For example, a QListView always only shows the first column, while one can hide or reorder columns in a QTableView).

As you use QStandardItemModel, its documentation should give a few hints how to create multiple columns.

E.g., look at this example from the documentation:

 QStandardItemModel model(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));
         model.setItem(row, column, item);
     }
 }

It creates a model with 4 initial rows and columns each, and then fills it with items via setItem().

Alternatively, you can pass a list of items to QStandardItemModel::appendRow(), with an item for each column:

QList<QStandardItem*> items;
items.append(new QStandardItem(tr("One"));
items.append(new QStandardItem(tr("Two"));
model->appendRow(items);

This adds a new row with "One' in the first column and "Two" in the second. For even more ways to deal with multiple columns, see the QStandardItemModel docs.

Note: QTreeView expects the same number of columns on all levels of the hierarchy, so one should fill rows with empty items for the unused columns if need be.

Frank Osterfeld
  • 24,815
  • 5
  • 58
  • 70
  • As you can see in my Code, I already did what you proposed. Using append() instead of << did not help. Appending the rows to m_model instead of item adds the second column at depth 0 instead of depth 1. – gartenriese Feb 01 '14 at 18:33
  • I clarified my question! – gartenriese Feb 02 '14 at 22:57
4

Just an addition to answer by Frank Osterfeld:

QTreeView displays all columns of subtables inserted into top level QStandardItems. You just have to "force" it to show additional columns by inserting dummy QStandardItems into top-level table. Example:

QStandardItemModel *objectTreeModel = new QStandardItemModel(NULL);
QStandardItem *mainItem = new QStandardItem(tr("Main Item"));
QStandardItem *subItem1 = new QStandardItem(tr("Sub-Item 1"));
QStandardItem *subItem2 = new QStandardItem(tr("Sub-Item 2"));
mainItem->appendRow(QList<QStandardItem *>() << subItem1 << subItem2);

QStandardItem *dummyItem = new QStandardItem();

objectTreeModel->appendRow(QList<QStandardItem *>() << mainItem << dummyItem );

Now you will be able to see 2 columns and if you expand mainItem, both subitems will be visible.

TimeS
  • 111
  • 2
  • 4
  • 1
    The penny dropped when I read this answer, "force" being the key word. Re-reading the ticked answer makes more sense now, but for me it was more implied than explicit, so this answer gets my upvote. The fact is if, for example, you forget to add an item to the last column for any one of the rows, the result is that no items in that column will be displayed. I expect Qt have their reasons for this but seems like a cryptic bug to me. Thanks for the answer. – mark sabido Mar 20 '18 at 23:05