Frage

Ich möchte in der Lage sein, zu erweitern oder alle Kinder eines bestimmten Zweiges in einem QTreeView kollabieren. Ich verwende PyQt4.

Ich weiß, dass QTreeView die haben ein erweitern alle Kinder verfügen, dass an * gebunden ist, aber ich brauche zwei Dinge: Es muss eine andere Tastenkombination gebunden sein (Shift-Raum) und ich muss auch in der Lage sein, alle zum Einsturz Kinder.

Hier ist, was ich versucht habe, so weit: Ich habe eine Unterklasse einer QTreeView wobei ich für die Shift-Leertaste Combo bin Überprüfung. Ich weiß, dass QModelIndex läßt mich ein bestimmtes Kind mit der „Kind“ Funktion wählen, aber das erfordert die Zahl der Kinder zu kennen. I am der Lage, eine Zählung der Kinder zu erhalten, indem an dem internalPointer suchen, aber das gibt mir nur Informationen für die erste Ebene der Hierarchie. Wenn ich versuche, Rekursion zu verwenden, ich ein paar Kind zählt bekommen, aber dann bin ich verloren, wie diese konvertiert zurück in eine gültige QModelIndex zu erhalten.

Hier ist ein Code:

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

Dies ist der Beginn der Rekursion Methode, die ich untersuchte, aber ich stecken bleiben, wenn sie tatsächlich den erweiterten Zustand zu setzen versuchen, weil einmal in der Rekursion, I „Kontakt“ mit jedem gültigen QModelIndex verlieren ...

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

Vielen Dank an alle für die in dieser Zeit zu Hinsehen!

War es hilfreich?

Lösung

Ok ... Geschwister eigentlich nicht bekommen, mich zu, wo ich hin wollte. Ich schaffte es, den Code zum Laufen zu bringen wie folgt (und es scheint wie eine ordentliche Umsetzung). Kudos noch Prof.Ebral, die hat mich auf dem richtigen Weg mit der Idee der Geschwister gehen (Kurven I benötigt QModelIndex.child (Zeile, Spalte) und Iterierte von dort rekursiv zu verwenden).

Beachten Sie, dass es die folgende Annahme im Code: Er geht davon aus, dass Ihre zugrunde liegenden Datenspeicher-Objekte die Fähigkeit haben, zu berichten, wie viele Kinder sie haben (get_child_count () in meinem Code). Wenn das nicht der Fall ist, müssen Sie irgendwie anders ein Kind Count ... vielleicht nur willkürlich versucht Kind Indizes zu erhalten - mit QModelIndex.child (row, col) - mit einer immer größeren Zeilenanzahl bis Sie zurück ein ungültiger Index? -. Das ist, was Prof.Ebral vorgeschlagen und ich könnte noch versuchen, dass (es ist nur, dass ich bereits eine einfache Möglichkeit habe, das Kind Zahl zu erhalten, indem es von meinem Datenspeicher anfordert)

Beachten Sie auch, dass ich collpase tatsächlich zeigen / jeden Knoten an einem anderen Punkt in der Rekursion basierend darauf, ob ich Ausdehnen oder Kollabieren. Dies liegt daran, durch Versuch und Irrtum, ich, dass die Ansichten animierten Baum entdeckt würden stottern und Pop, wenn ich tue es nur an einer Stelle im Code. Nun, durch Umkehrung der Reihenfolge, in der ich es tun, basierend auf, ob ich auf der obersten Ebene (das heißt die Wurzel der Branche Ich bin zu beeinflussen - nicht die Wurzel des gesamten treeview) ich eine schöne glatte Animation erhalten. Dies wird dokumentiert unten.

Der folgende Code ist in einer QTreeView Unterklasse.

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

Andere Tipps

model.rowCount (Index) ist die Methode, die Sie wollen.

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 (Zeile, Spalte, parent) ist im Wesentlichen der gleiche wie der Aufruf index.child (Zeile, Spalte); nur mit weniger Umwegen.

Ich würde empfehlen, einen QTreeWidget verwendet, die QTreeView erbt. Sie können dann die Kinder als QTreeWidgetItem greifen.

Da Sie nicht die QTreeWidget verwenden möchten, aber wollen Ihr aktuelles Modell bleiben .. können Sie durch die ‚möglichen‘ Kinder iterieren verwenden, .isValid (). obwohl Sie sollten nicht die internalPointer () verwenden. Stattdessen verwenden Sie die cellItem Sie haben, wie es der ursprüngliche ModalIndex ist .. dann versuchen, es Geschwister zu finden. So etwas wie

x = 0; y =0
while cellIndex.sibling(x, y).isValid():
    child = cellIndex.sibling(x, y)
    x += 1
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top