(PYQT) QtreeView - Хотите расширить / Свернуть всех детей и внуков

StackOverflow https://stackoverflow.com/questions/4100139

Вопрос

Я хочу быть в состоянии расширить или свернуть всех детей определенной отрасли в QtreeView. Я использую PYQT4.

Я знаю, что у QtreeView есть расширяющуюся функцию детей, которая связана с *, но мне нужны две вещи: его необходимо связать другую комбинацию ключей (Shift-Space), и мне также нужно быть в состоянии свернуть всех детей, а также Отказ

Вот то, что я пробовал до сих пор: у меня есть подкласс QtreeView, в котором я проверяю комбинацию ключа Shift-Space. Я знаю, что QModelindex позволит мне выбрать конкретный ребенок с функцией «ребенка», но это требует знания числа детей. я являюсь Возможность получить счет детей, глядя на InternationPointer, но это только дает мне информацию для первого уровня иерархии. Если я попытаюсь использовать рекурсию, я могу получить кучу дочерних средств, но тогда я потерян как для того, как получить их обратно в действительный 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

Спасибо всем за то, что потратить время, чтобы посмотреть на это!

Это было полезно?

Решение

Хорошо ... братья и сестры на самом деле не доставили меня туда, где я хотел пойти. Мне удалось получить код работы следующим образом (и кажется достойным реализацией). Кудос все еще к профессору, который заставил меня идти на правильный путь с идеей братьев и сестер (оказывается, мне нужно использовать qmodelindex.child (ряд, столбец) и повторять рекурсию).

Обратите внимание, что в коде есть следующее предположение: предполагается, что ваши основные объекты магазина данных имеют возможность сообщить, сколько у них детей (get_child_count () в моем коде). Если это не так, вы каким-то образом должны получить дочерний счет, по-разному ... возможно, просто произвольно пытаясь получить детские индексы - с помощью QModelindex.Child (ряд, сопол) - с постоянно растущей подсчетом строки, пока не вернетесь Неверный индекс? - Это то, что предложило Prof.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)

Другие советы

Model.Rowcount (индекс) - это метод, который вы хотите.

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 (строка, сопол, родитель) по существу совпадает с вызовом index.child (строка, сопол); Просто с меньшим количеством наблюдений.

Я бы порекомендовал использовать Qtreewidget, который наследует QtreeView. Затем вы можете захватить детей в качестве QtreewidgeteTem.

Поскольку вы не хотите использовать QtreeWidget, но хотите придерживаться своей текущей модели. Вы можете пережить через «возможные» дети, использующие, .isValid (). Вы не должны использовать InternationPointer (), хотя. Вместо этого используйте The CellItem, поскольку именно оригинал Modalindex. Затем попытайтесь найти его братья и сестры. Что-то вроде

x = 0; y =0
while cellIndex.sibling(x, y).isValid():
    child = cellIndex.sibling(x, y)
    x += 1
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top