5

我正在QTreeWidget从一个 XML 文件中创建一个。XML 如下所示,我想创建一个名称树:

<root>
    <f name='foo'>bar
        <f name='foo2'>baz</f>
    </f>
</root>

目前我正在使用以下代码来执行此操作(有些简化的代码)

import lxml.etree as et

#...

self.xml = et.XML(filters.filtersxml)
self.tree_widget = QTreeWidget(parent)

def add_items(parent, xmlroot):
    for i in xmlroot.getchildren():
        item = QTreeWidgetItem(parent, [i.get('name')])
        if len(i.getchildren()) != 0:
            add_items(item, i)

add_items(self.tree_widget, self.xml)

我实际上对此有两个问题:

  1. 主要问题:有没有办法选择树中的第一个项目,在这种情况下是 foo 。我试图用setCurrentItem()and做一些事情setCurrentIndex(),但无法让它工作。我用谷歌搜索了一下,但我发现的所有解决方案都适用于模型。
  2. (可选)这个递归函数是一个很好的方法,还是有更好的方法?
4

1 回答 1

10

递归很好,会保持这种状态,并回答您的主要问题:

# after all your code
add_items(self.tree_widget, self.xml)

# select the root item
self.tree_widget.setCurrentItem(self.tree_widget.topLevelItem(0))

您只需确保在调用 setCurrentItem 时该项目已添加到树中 - 否则它不会真正起作用。某些方法要求项目已经与树相关联(如 setExpanded 和 setSelected)

编辑

要在不影响树的情况下递归构建,您可以执行以下操作:

import lxml.etree as et

#...

self.xml = et.XML(filters.filtersxml)
self.tree_widget = QTreeWidget(parent)

def add_items(parent, xmlroot):
    output = []
    for i in xmlroot.getchildren():
        item = QTreeWidgetItem(parent, [i.get('name')])
        output.append(item)
        if len(i.getchildren()) != 0:
            add_items(item, i)
    return output

items = add_items(None, self.xml)
self.tree_widget.addTopLevelItems(items)
self.tree_widget.setCurrentItem(items[0])

编辑2:一次加载

为了进一步深入兔子洞,我个人会尽可能减少不必要的调用和列表的方法是只为孩子构建一次循环:

import lxml.etree as et

#...

self.xml = et.XML(filters.filtersxml)
self.tree_widget = QTreeWidget(parent)

def create_item(parent, xmlroot):
    item = QTreeWidgetItem(parent, [xmlroot.get('name')])
    for xmlchild in xmlroot.getchildren():
       create_item(item, xmlchild)
    return item

items = [create_item(None, xmlchild) for xmlchild in self.xml.getchildren()]
self.tree_widget.addTopLevelItems(items)
if ( items ):
    self.tree_widget.setCurrentItem(items[0])

编辑 3:动态加载

并且由于它被提出......一种动态加载子级的方法是存储每个级别并在扩展后加载它们:

import lxml.etree as et
from PyQt4.QtGui import QTreeWidgetItem

# ...    

class XmlTreeWidgetItem(QTreeWidgetItem):
    def __init__( self, parent, xmlitem ):
        super(MyTreeWidgetItem, self).__init__(parent)
        self.setText(0, xmlitem.get('name'))
        self.setChildIndicatorPolicy(self.ShowIndicator)

        self._xmlitem = xmlitem
        self._loaded = False

    def loadChildren( self ):
        if ( self._loaded ):
            return

        self._loaded = True
        self.setChildIndicatorPolicy(self.DontShowIndicatorWhenChildless)
        for xmlchild in self._xmlitem.getchildren():
            XmlTreeWidgetItem(self, xmlchild)

# ...

class SomeClass(QWidget):
    def __init__( self, parent = None ):
        super(SomeClass, self).__init__(parent)

        self.tree_widget = QTreeWidget(parent)

        xml = et.XML(filters.filtersxml)
        items = [XmlTreeWidgetItem(None, xchild) for xchild in xml.getchildren()]
        self.tree_widget.addTopLevelItems(items)
        if ( items ):
            self.tree_widget.setCurrentItem(items[0])

        # create connections
        self.tree_widget.itemExpanded.connect(self.loadItem)

    def loadItem( self, item ):
        item.loadChildren()
于 2012-08-16T23:27:13.543 回答