简体   繁体   中英

dynamic qtreeview with custom delegates

I'm using Qt 5.6 and my goal is to develop a dynamic tree using QTreeView that needs to populate items such as combo boxes, edit box, checkbox, buttons..etc depending on the settings loaded and the tree data can change as new data is loaded. There will be many nodes to populate in the tree with parent and child nodes.

I've read about different options to implement this type of treeview such as populating a QTreeView and implementing my own delegate by inheriting from QITemDelegate or QStyledItemDelegate or using Qt Quick's QML treeview.

For my purposes I've chosen the first option to dynamically populate a tree and modify parameters but I'm having trouble setting the delegate i want for a selected cell only as the only options to set the delegate in the tree is to setItemDelegateForRow, setItemDelegateForColumn or setItemDelegate. The tree will look something like the below. How should i set a different delegate for each of the child nodes?

by (col, row)

Parent(cell 0,0)
  ->Child(cell 0,1) -combo box(1,1)
  ->Child(cell 0,2) -button(1,2)
  ->Child(cell 0,3) -check box(1,3)
 ...
 ...etc

Parent(cell 0,10)
  ->Child(cell 0,11) - edit box(1,11)
  ->Child(cell 0,12) - edit box(1,12)
  ->Child(cell 0,13) - check box(1,13)
 ...
 ...etc

Edit

This is a simplified version of how I have setup my tree view so far. Found out the answer to why my child node column 1 was not showing was because i did not set the column count of the model. I have updated the code below and it works now.

enum EditType
{
    TYPE_Text,
    TYPE_CheckBox,
    TYPE_ComboBox,
    TYPE_Button
};

QTreeView* tree = new QTreeView(this);
QStandardItemModel* model = new QStandardItemModel; 
model->setColumnCount(2);
tree->setModel(model);

//set custom delegate for column 1 of the tree 
CustomDelegate *customDelegate = new CustomDelegate(this);
tree->setItemDelegateForColumn(1, customDelegate); 

// Add parent nodes
QStandardItem* parent1 = new QStandardItem(tr("parent1"));
QStandardItem* parent2 = new QStandardItem(tr("parent2"));

model->appendRow(parent1);
model->appendRow(parent2);

// add a child
QList<QStandardItem*> childrow;
QStandardItem* child = new QStandardItem(tr("child1"));
childrow.append(child);
QStandardItem* child_value = new QStandardItem();
child_value->setData(TYPE_ComboBox, Qt::UserRole);
childrow.append(child_value);
parent1->appendRow(it_child);

As you can see from QAbstractItemView documentation , there is only methods for set delegate for
whole view, for columns or for rows. As you noticed, this methods are: setItemDelegate , setItemDelegateForColumn , setItemDelegateForRow . That's why you can not set delegate for certain cell.

There is another way, you can use for showing different widgets in QTreeView - method SetIndexWidget of QAbstractItemView . But you must keep in mind that:

This function should only be used to display static content within the visible area corresponding to an item of data. If you want to display custom dynamic content or implement a custom editor widget, subclass QItemDelegate instead.

Use SetIndexWidget method is very "expensive" and if you have many rows in you QTreeView , you can see performance degradation.

Addition: If you need widgets in QTreeView only for edit data items from your model, the best way to solve you problem will be reimplement QStyledItemDelegate . Look for method createEditor .

Addition: Example of reimplement QStyledItemDelegate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM