python/pyside 在qtreewidget中使用自定义控件

1 投票
1 回答
3647 浏览
提问于 2025-04-17 17:43

我在用Python3和pyside。现在我有一个Python字典,想把它显示成树形结构,使用Qt来实现。我希望值是可以编辑的,但键是不可以的。我已经通过setItemWidget这个方法实现了,下面是一个例子:

#!/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_())

这个方法是可行的,但和文档上说的(静态内容)有点不符,而且这样做会让我们无法提前创建这个小部件(比如在另一个线程中),然后再把它添加到树里。有没有更好的方法来实现我想要的效果?文档提到了QTreeView,但我没有找到任何例子或教程,能让我明白它是如何帮助我在某一列使用自己的小部件的。

1 个回答

2

你可以考虑两个选项:

  • 第一个选项是创建一个自己的类,这个类是 QTreeWidget 的子类。这种方法很简单,你只需要把你已有的方法放到这个类里就行了。不过这样做其实变化不大,只是调用你自定义的控件时看起来更“自然”一些。

  • 第二个方法,可能是你在提到文档时所指的,就是模型/视图架构。

在这种情况下,你需要使用 QTreeView 并创建自己的 QTreeModel。这里,视图完全不知道数据是什么,而模型负责提供所有数据,并在数据准备好显示时通知视图。所以你需要创建这个对象,并在数据准备好或发生变化时发出信号,以便视图能够更新。

如果你想了解如何实现类似的功能,可以查看 PySide 提供的示例。你很可能已经安装了它们,可以在 site-packages/PySide/examples/itemviews/simpletreemodel 找到。

另外,建议你看看 indexWidget 方法,这样你就可以在需要的地方添加你的 QEditLine,并调用父类的方法来获取默认行为。

撰写回答