QTreeWidget 选择第一项

Posted

技术标签:

【中文标题】QTreeWidget 选择第一项【英文标题】:QTreeWidget select first item 【发布时间】:2012-08-16 23:15:39 【问题描述】:

我正在从 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)

我其实有两个问题:

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

我认为通常你会在树外构建项目,然后获取单个根项目(如果它是这样设计的)或***项目列表并执行:insertTopLevelIteminsertTopLevelItems 是的,我通常也是这样做的...不确定哪个更好或更快,所以我会说两者都是可行的。我还建议在 blockSignals(True/False) 和 setUpdatesEnabled(False/True) 调用中对这样的树小部件进行任何修改。 好吧,我认为如果您确保首先构建您的项目结构,然后最后通过一次调用将其添加到树中,您就不必担心这一点。但是,当您在循环中随机添加和删除项目时,这是一个好点 这真的取决于你想要做什么——有时我需要能够在创建过程中引用一个项目的树小部件,所以我在创建过程中将它们添加到树中,而不是事后,在这种情况下我阻止发送信号。大多数时候我同意 jdi,在树外构建然后在最后添加***项目是最简单的方法。我使用递归方式编辑了答案,而无需先分配给树。 是的,这是一个很好的问题和话题。干杯,伙计们。我刚刚用一个没有递归的动态加载的例子再次更新了答案。

以上是关于QTreeWidget 选择第一项的主要内容,如果未能解决你的问题,请参考以下文章

qtreewidget设置正则表达式

QTreeWidget;在 QTree 中选择多个项目时禁用 ui 功能

QTreeWidget中项目周围的选定效果

如何将 QTreeWidget 的子项设置为在单击其父项时自动选择并突出显示

DropDownList绑定数据后,选择项始终是第一项,选择别的,输出的还是第一项,求解?

MySQL GROUP BY 返回第一项 - 需要选择最后一项