(PyQt)QTreeView-要展开/折叠所有子代和子代吗

(PyQt)QTreeView-要展开/折叠所有子代和子代吗,qt,pyqt,expand,collapse,qtreeview,Qt,Pyqt,Expand,Collapse,Qtreeview,我希望能够在QTreeView中展开或折叠特定分支的所有子级。我正在使用PyQt4 我知道QTreeView的“扩展所有子项”功能绑定到*,但我需要两件事:它需要绑定到不同的键组合(移位空间),我还需要能够折叠所有子项 以下是我迄今为止所尝试的: 我有一个QTreeView的子类,其中我正在检查shift空格键组合。我知道QModelIndex将允许我使用“child”函数选择一个特定的子对象,但这需要知道子对象的数量。我可以通过查看internalPointer来获得子级的计数,但这只提供层次

我希望能够在QTreeView中展开或折叠特定分支的所有子级。我正在使用PyQt4

我知道QTreeView的“扩展所有子项”功能绑定到*,但我需要两件事:它需要绑定到不同的键组合(移位空间),我还需要能够折叠所有子项

以下是我迄今为止所尝试的: 我有一个QTreeView的子类,其中我正在检查shift空格键组合。我知道QModelIndex将允许我使用“child”函数选择一个特定的子对象,但这需要知道子对象的数量。我可以通过查看internalPointer来获得子级的计数,但这只提供层次结构第一级的信息。如果我尝试使用递归,我可以得到一堆子计数,但是我不知道如何将它们转换回有效的QModelIndex

下面是一些代码:

def keyPressEvent(self, event):
    """
    Capture key press events to handle:
    - enable/disable
    """
    #shift - space means toggle expanded/collapsed for all children
    if (event.key() == QtCore.Qt.Key_Space and 
        event.modifiers() & QtCore.Qt.ShiftModifier):
        expanded = self.isExpanded(self.selectedIndexes()[0])
        for cellIndex in self.selectedIndexes():
            if cellIndex.column() == 0: #only need to call it once per row
                #I can get the actual object represented here
                item = cellIndex.internalPointer()
                #and I can get the number of children from that
                numChildren = item.get_child_count()
                #but now what? How do I convert this number into valid
                #QModelIndex objects? I know I could use: 
                #   cellIndex.child(row, 0)
                #to get the immediate children's QModelIndex's, but how
                #would I deal with grandchildren, great grandchildren, etc...
                self.setExpanded(cellIndex, not(expanded))
        return
这是我正在研究的递归方法的开始,但我在实际尝试设置扩展状态时遇到了困难,因为一旦进入递归,我就失去了与任何有效QModelIndex的“联系”

def toggle_expanded(self, item, expand):
    """
    Toggles the children of item (recursively)
    """
    for row in range(0,item.get_child_count()):
        newItem = item.get_child_at_row(row)
        self.toggle_expanded(newItem, expand)
    #well... I'm stuck here because I'd like to toggle the expanded
    #setting of the "current" item, but I don't know how to convert
    #my pointer to the object represented in the tree view back into
    #a valid QModelIndex
    #self.setExpanded(?????, expand)   #<- What I'd like to run
    print "Setting", item.get_name(), "to", str(expand) #<- simple debug statement that indicates that the concept is valid
def切换_展开(自、项、展开):
"""
切换项的子项(递归)
"""
对于范围(0,item.get_child_count())中的行:
newItem=item.get_child_在_行(行)
self.toggle_展开(新建项,展开)
#嗯。。。我被困在这里,因为我想切换扩展的
#“当前”项的设置,但我不知道如何转换
#指向树视图中表示的对象的指针返回到
#有效的QModelIndex
#self.setExpanded(???,expand)#我建议使用继承QTreeView的QTreeWidget。然后可以将这些子项作为QTreeWidgetItem抓取

因为您不想使用QTreeWidget,而是想坚持使用当前模型。。您可以使用.isValid()遍历“可能”的子项。但是,不应该使用internalPointer()。而是使用您拥有的cellItem,因为它是原始的ModalIndex。。然后试图找到它的兄弟姐妹。差不多

x = 0; y =0
while cellIndex.sibling(x, y).isValid():
    child = cellIndex.sibling(x, y)
    x += 1

好的。。。实际上,兄弟姐妹并没有把我带到我想去的地方。我设法使代码按如下方式工作(它看起来是一个不错的实现)。Ebral教授让我走上了兄弟姐妹的正确道路(结果证明我需要使用QModelIndex.child(行、列)并从那里递归迭代),这仍然是我的荣幸

请注意,代码中有以下假设:它假设底层数据存储对象能够报告它们有多少子对象(在我的代码中为get_child_count())。如果不是这样的话,你将不得不以不同的方式计算孩子的数量。。。也许只是任意尝试获取子索引——使用QModelIndex.child(row,col)——并不断增加行数,直到返回无效索引这是Ebral教授的建议,我可能仍然会尝试(只是我已经有了一种从我的数据存储中请求孩子数的简单方法)

还要注意,我实际上是在递归中的不同点上展开/合并每个节点,具体取决于我是在展开还是在折叠。这是因为,通过反复试验,我发现,如果我只在代码中的某个位置执行动画,则动画树视图会结巴并弹出。现在,根据我是否处于顶层(即我所影响的分支的根,而不是整个树视图的根),颠倒我的操作顺序,我得到了一个很好的平滑动画。这一点记录如下

以下代码位于QTreeView子类中

#---------------------------------------------------------------------------
def keyPressEvent(self, event):

    if (event.key() == QtCore.Qt.Key_Space and self.currentIndex().column() == 0):
        shift = event.modifiers() & QtCore.Qt.ShiftModifier
        if shift:
            self.expand_all(self.currentIndex())
        else:                
            expand = not(self.isExpanded(self.currentIndex()))
            self.setExpanded(self.currentIndex(), expand)


#---------------------------------------------------------------------------
def expand_all(self, index):
    """
    Expands/collapses all the children and grandchildren etc. of index.
    """
    expand = not(self.isExpanded(index))
    if not expand: #if collapsing, do that first (wonky animation otherwise)
        self.setExpanded(index, expand)    
    childCount = index.internalPointer().get_child_count()
    self.recursive_expand(index, childCount, expand)
    if expand: #if expanding, do that last (wonky animation otherwise)
        self.setExpanded(index, expand)


#---------------------------------------------------------------------------
def recursive_expand(self, index, childCount, expand):
    """
    Recursively expands/collpases all the children of index.
    """
    for childNo in range(0, childCount):
        childIndex = index.child(childNo, 0)
        if expand: #if expanding, do that first (wonky animation otherwise)
            self.setExpanded(childIndex, expand)
        subChildCount = childIndex.internalPointer().get_child_count()
        if subChildCount > 0:
            self.recursive_expand(childIndex, subChildCount, expand)
        if not expand: #if collapsing, do it last (wonky animation otherwise)
            self.setExpanded(childIndex, expand)
rowCount(index)是您想要的方法

model = index.model()   # or some other way of getting it
for i in xrange(model.rowCount(index)):
  child = model.index(i,0, index)
  # do something with child

model.index(row,col,parent)本质上与调用index.child(row,col)相同;只需较少的间接操作。

谢谢,但我非常致力于使用模型/视图框架,据我所知,我无法使用QTreeWidget,我可以吗?从文档中可以看出,QTreeWidget类是一个方便的类,它提供了一个标准的树小部件,具有一个与Qt3中QListView类使用的类似的基于项的经典接口。这个类基于Qt的模型/视图体系结构,使用默认模型来保存项目,每个项目都是QTreeWidgetItem。但是由于我已经有了一个模型,可以做很多自定义工作,我仍然认为我无法切换,因为内置在QTreeWidget中的默认模型不会做任何我需要它做的事情。好的。。那我再看看,兄弟姐妹们!这可能就是问题所在。谢谢