python/pyside using a custom widget in a qtreewidg

2019-08-07 05:20发布

问题:

Using Python3 and pyside. I have a python dictionary which I want to display as a tree using Qt. I want the values to be editable but not the keys. I have managed to achieve this using setItemWidget as shown in the following example:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PySide import QtGui

def data_to_tree(parent, data):
    if isinstance(data, dict):
        parent.setFirstColumnSpanned(True)
        for key,value in data.items():
            child = QtGui.QTreeWidgetItem(parent)
            child.setText(0, key)
            data_to_tree(child, value)
    elif isinstance(data, list):
        parent.setFirstColumnSpanned(True)
        for index,value in enumerate(data):
            child = QtGui.QTreeWidgetItem(parent)
            child.setText(0, str(index))
            data_to_tree(child, value)
    else:
        widget = QtGui.QLineEdit(parent.treeWidget())
        widget.setText(str(data))
        parent.treeWidget().setItemWidget(parent, 1, widget)

app = QtGui.QApplication(sys.argv)

wid = QtGui.QTreeWidget()
wid.setColumnCount(2)
wid.show()

data = {
    'foo':'bar',
    'bar': ['f', 'o', 'o'],
    'foobar':0,
}
data_to_tree(wid.invisibleRootItem(), data)

sys.exit(app.exec_())

This works, but it goes against what the documentation advises (static content) and makes it impossible to create the widget beforehand (in a separate thread for example) and then add it to the tree. Is there any better way to achieve what I want? Documentation mention QTreeView but I haven't found any example/tutorial that let me understand how it would help me use my own widget in a column.

回答1:

There are 2 options you might want to consider:

  • You can create your own class which is a subclass of a QTreeWidget. This is straightforward as you simply just use the method you have as is and put it inside the class. But this does not really change a lot, except for the fact that it will look more "natural" when calling this on your custom widget.

  • The other method, which is what you are most probably referencing when talking about the documentation is the Model/View architecture.

In that case, you will have to use the QTreeView and create your own QTreeModel. Here, the view has absolutely no idea what the data is, and the model is responsible for providing all the data, and notifying the view when it's ready to display. So you have to make that object and emit a signal when the data is ready/changes, so that the view is updated.

For an idea of how you can implement something similar you can have a look at the examples provided with PySide. Most probably you have them installed, look in site-packages/PySide/examples/itemviews/simpletreemodel.

Also, consider looking into the indexWidget method so that you can add your QEditLine where needed and call the parent for the default.