QTreeWidget选择第一项

时间:2012-08-16 23:15:39

标签: python qt pyqt pyside

我正在从XML文件中创建QTreeWidget。 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()setCurrentIndex()执行某些操作,但无法使其正常工作。我已经搜索了一下,但我发现的所有解决方案都适用于模型。
  2. (可选)这个递归函数是一个很好的方法吗,还是有更好的方法?

1 个答案:

答案 0 :(得分:9)

递归是好的,会保持这种方式,并回答你的主要问题:

# 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()