5

QTreeWidgetXMLファイルからを作成しています。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)

私は実際にこれについて2つの質問があります:

  1. 主な質問:ツリーの最初の項目(この場合はfoo)を選択する方法はありますか?setCurrentItem()とで何かをしようとしまし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:一度にすべてロード

そして、うさぎの穴をもう少し下に行くために、私が個人的にこれを行って不要な呼び出しとリストを可能な限り最小限に抑える方法は、子のループを1回だけ構築することです。

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 に答える