Domanda

Voglio essere in grado di espandere o comprimere tutti figli di un particolare ramo in un QTreeView. Sto usando PyQt4.

So che QTreeView sono un'espansione tutti i bambini caratteristica che è destinata a *, ma ho bisogno di due cose: Ha bisogno di essere legato a una combinazione di tasti diversa (shift-spazio) e ho anche bisogno di essere in grado di collassare tutto i bambini.

Ecco quello che ho provato finora: Ho una sottoclasse di un QTreeView in cui sto controllando per la chiave combinata shift-spazio. So che QModelIndex mi permette di scegliere un bambino specifico con la funzione di "bambino", ma che richiede la conoscenza del numero di figli. I am in grado di ottenere un conteggio dei bambini, cercando al internalPointer, ma che mi dà solo informazioni per il primo livello della gerarchia. Se provo ad usare la ricorsione, posso avere un po 'di conti bambino, ma poi mi sono perso su come ottenere queste indietro convertito in un QModelIndex valido.

Ecco il codice:

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

Ecco l'inizio del metodo ricorsione stavo indagando, ma mi si blocca quando in realtà cercando di impostare lo stato espanso perché una volta all'interno della ricorsione, perdo "contatto" con qualsiasi QModelIndex valida ...

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

Grazie a tutti per aver il tempo di dare un'occhiata a questo!

È stato utile?

Soluzione

Ok ... fratelli non ha in realtà mi arrivare dove volevo andare. Sono riuscito ad ottenere il codice di lavoro come segue (e sembra che un'implementazione decente). Complimenti ancora Prof.Ebral che ha ottenuto mi fa andare avanti sulla strada giusta con l'idea di fratelli (risulta avevo bisogno di usare QModelIndex.child (riga, colonna) e iterate ricorsivamente da lì).

Si noti che non v'è la seguente assunzione in codice: Si presuppone che gli oggetti dati sottostante hanno la capacità di segnalare quanti bambini hanno (get_child_count () nel mio codice). Se questo non è il caso, sarà in qualche modo deve ottenere un conteggio bambino diversamente ... forse semplicemente arbitrariamente cercando di ottenere indici bambino - usando QModelIndex.child (riga, colonna) - con un conteggio di righe sempre crescente fino ad ottenere indietro un indice non valido? -. Questo è ciò che ha suggerito Prof.Ebral e potrei ancora provare che (è solo che ho già un modo facile per ottenere il conteggio bambino richiedendolo dal mio archivio dati)

Si noti inoltre che in realtà espando / comprimi ciascun nodo in un punto diverso nel ricorsione basato su se sto espandendo o collasso. Questo perché, attraverso tentativi ed errori, ho scoperto che viste ad albero animati sarebbero balbettare e pop se ho appena fatto in un unico posto nel codice. Ora, invertendo l'ordine in cui lo faccio in base a se sono al livello più alto (cioè la radice del ramo che sto che colpisce - non la radice di tutta la vista ad albero) ottengo un bel un'animazione fluida. Questo è documentato qui di seguito.

Il seguente codice è in una sottoclasse 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)

Altri suggerimenti

model.rowCount (indice) è il metodo che si desidera.

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 (riga, colonna, genitore) è essenzialmente la stessa come chiamata index.child (riga, colonna); solo con un minor numero indirections.

Ti consiglio di utilizzare una QTreeWidget che eredita QTreeView. È quindi possibile prendere i bambini come un QTreeWidgetItem.

Dal momento che non si desidera utilizzare il QTreeWidget ma vuole attaccare al vostro modello attuale .. è possibile scorrere le 'possibili' bambini che utilizzano, .isValid (). Si consiglia di non utilizzare l'internalPointer () però. Invece utilizzare il cellItem hai, come lo è l'originale ModalIndex .. poi tentare di trovarla di fratelli. Qualcosa di simile

x = 0; y =0
while cellIndex.sibling(x, y).isValid():
    child = cellIndex.sibling(x, y)
    x += 1
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top