PDA

View Full Version : How to set widgets as children items on QTreeView



q130s
8th March 2013, 02:39
Is it possible to add widgets to the children items on QTreeView?

Thanks to [this thread on stackoverflow](http://stackoverflow.com/questions/9668983/qtreeview-vs-setindexwidget), I'm able to add widgets to 2nd or later column of `QAbstractItemView` (in my example QTreeView of top level items of a view.

Here's what I've tried which partly went well:



#!/usr/bin/env python
import os

from PyQt4.QtCore import QModelIndex, Qt
from PyQt4.QtGui import QApplication, QItemSelectionModel, \
QPushButton, QStandardItem, \
QStandardItemModel, QTreeView
from PyQt4.uic import loadUi


class PrvTreeviewNest(QTreeView):
def __init__(self):
super(PrvTreeviewNest, self).__init__()

loadUi('/home/user/yourproject/resource/treeview_nest.ui')

# row can be 0 even when it's more than 0.
self._datamodel = QStandardItemModel(0, 2)
self.setModel(self._datamodel)

for i in range(4):
self._add_widget(i + 1)

self.show()

def _add_widget(self, n):
std_item = QStandardItem('{}th item'.format(n))
self._datamodel.setItem(n, 0, std_item)

node_widget = QPushButton('{}th button'.format(n))
qindex_widget = self._datamodel.index(n, 1, QModelIndex())
self.setIndexWidget(qindex_widget, node_widget)

if n == 2:
std_item_child = QStandardItem('child')
std_item.appendRow(std_item_child)

node_widget_child = QPushButton('petit button')
qindex_widget_child = self._datamodel.index(n, 1, QModelIndex())
self.setIndexWidget(qindex_widget_child, node_widget_child)

if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = PrvTreeviewNest()
window.resize(320, 240)
window.setWindowTitle(
QApplication.translate("toplevel", "Top-level widget"))

sys.exit(app.exec_())


[treeview_nest.ui](http://pastebin.com/G0DhQay3) is available.

You see in the image below that the item `child` doesn't show a button and its parent's button is overwritten. Apparently I have no idea how to write a code for it.
8802

wysota
8th March 2013, 10:52
Is it possible to add widgets to the children items on QTreeView?
Yes and no. Yes, because you can use setIndexWidget(), no because it only puts the widget in the view but has no relation to items of the view (or model). And you really want to avoid it for performance reasons. If you want only a button then you can implement it with a custom delegate. If you want something more than a button then I you might want to use QScrollArea with real widgets instead of a view.

q130s
10th March 2013, 00:23
I figured out how to add widget to children. Tricky enough, using QStandardItem.insertRow (http://qt-project.org/doc/qt-4.8/qstandarditem.html#insertRow) combined with index does the work. In my sample code above, replace `_add_widget` with the following:



def _add_widget(self, n):
item_toplevel = QStandardItem('{}th item'.format(n))
self._datamodel.setItem(n, 0, item_toplevel)

widget_toplevel = QPushButton('{}th button'.format(n))
qindex_toplevel = self._datamodel.index(n, 1, QModelIndex())
self.setIndexWidget(qindex_toplevel, widget_toplevel)

if n == 2:
item_child_col0 = QStandardItem('child col0')
item_child_col1 = QStandardItem('child col1')
#item_toplevel.appendRow(item_child_col0)

item_toplevel.insertRow(0, [item_child_col0, item_child_col1])

widget_child = QPushButton('child widget')
qindex_child = item_child_col1.index()
self.setIndexWidget(qindex_child, widget_child)


I'm sure this is NOT the best/ideal designed way but seems to work for me.

8805

Added after 5 minutes:

@wysota thanks for the reply. Nice to know the reasoning behind setIndexWidget(). However I was asking about how I can add widget as "CHILDREN" to QTreeView (or I might better say "How can I use widgets as hierarchical tree nodes on QTreeView"). I managed to figure out as I posted it already. Any thoughts about it is appreciated!

wysota
10th March 2013, 00:40
However I was asking about how I can add widget as "CHILDREN" to QTreeView (or I might better say "How can I use widgets as hierarchical tree nodes on QTreeView"). I managed to figure out as I posted it already. Any thoughts about it is appreciated!

Actually you were asking about how to add widgets as children of the view's viewport. And that's what setIndexWidget does. Which is what you shouldn't do as I already said. You have 5 items here. Try doing that for 5000 items.