(PyQt)QTreeView-想要扩展/折叠所有子孙 [英] (PyQt) QTreeView - want to expand/collapse all children and grandchildren

查看:209
本文介绍了(PyQt)QTreeView-想要扩展/折叠所有子孙的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to be able to expand or collapse all children of a particular branch in a QTreeView. I am using PyQt4.

我知道QTreeView具有绑定到*的扩展所有子代功能,但是我需要两件事:它需要绑定到另一个组合键(Shift-空格键),我还需要能够折叠所有孩子。

I know that QTreeView's have an expand all children feature that is bound to *, but I need two things: It needs to be bound to a different key combination (shift-space) and I also need to be able to collapse all children as well.

这是我到目前为止尝试过的:
我有一个QTreeView的子类,其中我正在检查shift-space键组合。我知道QModelIndex可以让我通过 child功能选择一个特定的孩子,但这需要知道孩子的数量。我 am 能够通过查看internalPointer来获得孩子的数量,但这只能为我提供层次结构第一级的信息。如果我尝试使用递归,我可以得到很多子计数,但是然后我就如何将这些转换回有效的QModelIndex一无所知。

Here is what I have tried so far: I have a subclass of a QTreeView wherein I am checking for the shift-space key combo. I know that QModelIndex will let me pick a specific child with the "child" function, but that requires knowing the number of children. I am able to get a count of the children by looking at the internalPointer, but that only gives me info for the first level of the hierarchy. If I try to use recursion, I can get a bunch of child counts, but then I am lost as to how to get these converted back into a valid 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的联系 ...

Here is the beginning of the recursion method I was investigating, but I get stuck when actually trying to set the expanded state because once inside the recursion, I lose "contact" with any valid 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

感谢大家花时间看这个!

Thanks to all for taking the time to look at this!

推荐答案

好吧……兄弟姐妹实际上并没有把我带到我想去的地方。我设法使代码按如下方式工作(这似乎是一个不错的实现)。仍然对Ebral教授表示敬意,他使我对兄弟姐妹的想法正确了(原来我需要使用QModelIndex.child(row,column)并从那里递归地进行迭代。)

Ok... siblings did not actually get me to where I wanted to go. I managed to get the code working as follows (and it seems like a decent implementation). Kudos still to Prof.Ebral who got me going on the right track with the idea of siblings (turns out I needed to use QModelIndex.child(row, column) and iterate recursively from there).

请注意,代码中存在以下假设:假设您的基础数据存储对象具有报告它们拥有多少子代的能力(在我的代码中为get_child_count())。如果不是这种情况,您将不得不以某种方式获得不同的子项计数……也许只是通过使用QModelIndex.child(row,col)任意尝试获取子项索引-行数不断增加,直到返回无效的索引? -这是Ebral教授的建议,我仍然可以尝试(这只是我已经有了一种简单的方法,可以通过从我的数据存储区中请求获取孩子的数量)。

Note that there is the following assumption in the code: It assumes that your underlying data store objects have the ability to report how many children they have (get_child_count() in my code). If that is not the case, you will somehow have to get a child count differently... perhaps by just arbitrarily trying to get child indexes - using QModelIndex.child(row, col) - with an ever increasing row count till you get back an invalid index? - this is what Prof.Ebral suggested and I might still try that (It is just that I already have an easy way to get the child count by requesting it from my data store).

还要注意,实际上我是根据扩展还是崩溃来在递归的不同点扩展/折叠每个节点。这是因为,通过反复试验,我发现,如果我只是在代码中的某个位置这样做,动画树视图就会结结巴巴并弹出。现在,通过根据我是否处于顶层(即,我正在影响的分支的根-而不是整个树视图的根)来反转执行顺序,我得到了一个很好的平滑动画。

Also note that I actually expand/collpase each node at a different point in the recursion based on whether I am expanding or collapsing. This is because, through trial and error, I discovered that animated tree views would stutter and pop if I just did it at one place in the code. Now, by reversing the order in which I do it based on whether I am at the top level (i.e. the root of the branch I am affecting - not the root of the entire treeview) I get a nice smooth animation. This is documented below.

以下代码在QTreeView子类中。

The following code is in a QTreeView subclass.

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

这篇关于(PyQt)QTreeView-想要扩展/折叠所有子孙的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆