Domanda

[Questa è una versione aggiornata di una domanda pubblicata in precedenza, il titolo precedente era Selezione nodo indice in Virtual TreeView di Delphi .]

Dopo la parte migliore di un giorno, credo che ho la componente Treeview virtuale (potente ma complesso) che lavorano in un due dati della tabella modo semplice conoscenza.

Ora, sto cercando di selezionare semplicemente il 1512i (per esempio) dei nodi di primo livello. Non riesco a vedere un modo per fare questo altro che ottenere il primo nodo di primo livello e quindi chiamando getNextSibling 1.511 in un ciclo.

Questo sembra inutilmente coinvolti. C'è un modo più semplice?

Aggiorna

Perché l'inizializzazione i nodi nel mio albero richiede l'accesso al database, l'inizializzazione tutti i nodi in fase di avvio non è fattibile. Quando l'utente inizia con la forma con la fedina già selezionata, va bene. Come l'utente scorre intorno all'albero, i nodi vengono compilati sufficienti per visualizzare la finestra corrente contro l'albero e la performance va bene.

Quando l'utente avvia il modulo in modalità di dialogo con un record di database già selezionato, devo far avanzare l'albero a quel nodo prima che l'utente vede il modulo. Questo è un problema perché, se il record è verso la fine dell'albero, si può prendere dieci secondi mentre cammino l'albero dal primo nodo. Ogni volta che posso getNextSibling (), un nodo viene inizializzato, anche se la maggior parte dei nodi non vengono visualizzati all'utente. Io preferirei rimandare l'inizializzazione di quei nodi al punto in cui diventano visibili per l'utente.

So che ci deve essere un modo migliore, perché se apro l'albero senza un record selezionato e utilizzare la barra di scorrimento verticale a muoversi, in una sola operazione, al centro della struttura, allora vengono visualizzati i nodi corretti < em> senza dover inizializzare i nodi ho saltato sopra .

Questo è l'effetto che vorrei raggiungere quando si apre l'albero con un record selezionato. So che l'indice del nodo che voglio andare, ma se non posso arrivare con indice avrei potuto fare una ricerca binaria sull'albero assumendo posso saltare un numero di nodi avanti e indietro (simile a scorrimento direttamente al centro dell'albero).

In alternativa, forse c'è qualche impostazione Stato posso fare a vista ad albero che lascerà i nodi intermedi non inizializzati come mi attraversano la griglia. Ho provato Begin / End Update e che non sembra fare il trucco.

È stato utile?

Soluzione

Per ottenere fratello di un nodo senza inizializzarla, basta utilizzare il puntatore NextSibling (vedi dichiarazione di TVirtualNode).

Altri suggerimenti

Il controllo della struttura è strutturato proprio come gli alberi classici che ci si conoscere in un corso di computer-science. L'unico modo per ottenere dalla radice dell'albero al bambino 1512th è quello di camminare i link ad uno ad uno. Se lo fate voi stessi o si utilizza un metodo di controllo della struttura, che deve ancora essere fatto in quel modo. Non vedo nulla di previsto nel controllo stesso, in modo da poter utilizzare questa funzione:

function GetNthNextSibling(Node: PVirtualNode; N: Cardinal;
  Tree: TBaseVirtualTree = nil): PVirtualNode;
begin
  if not Assigned(Tree) then
    Tree := TreeFromNode(Node);
  Result := Node;
  while Assigned(Result) and (N > 0) do begin
    Dec(N);
    Result := Tree.GetNextSibling(Result);
  end;
end;

Se vi trovate a fare che spesso, si potrebbe desiderare di fare voi stessi un indice. Potrebbe essere semplice come fare un array di puntatori PVirtualNode e memorizzare tutti i valori principali in esso, in modo da poter semplicemente leggere il valore 1512th fuori di esso. Il controllo della struttura non ha bisogno di una tale struttura dati stessi, in modo che non mantiene uno.

Si potrebbe anche riconsiderare se si hanno bisogno di una struttura di dati del genere. Ti davvero hanno bisogno di accedere ai nodi in base all'indice del genere? O potrebbe invece mantenere un puntatore PVirtualNode, quindi la sua posizione rispetto al resto dei nodi nella struttura non ha più importanza (significa che è possibile, ad esempio, ordinarli senza perdere riferimento al nodo che si voleva)?

Si scrive nel vostro aggiornamento:

  

So che ci deve essere un modo migliore, perché se apro l'albero senza un record selezionato e utilizzare la barra di scorrimento verticale a muoversi, in una sola operazione, al centro della struttura, allora vengono visualizzati i nodi corretti < em> senza dover inizializzare i nodi ho saltato sopra .

Esiste una differenza qui, perché scorrimento verticale cambia la coordinata Y logico che viene visualizzato nella posizione client 0. Il controllo calcola lo spostamento dalla posizione di scorrimento e scorrere gamma, e quindi calcola quale nodo è visibile nella parte superiore del controllo . I nodi vengono inizializzati di nuovo solo quando la zona che è stata scorre in vista ha bisogno di essere dipinta.

Se avete la coordinata Y di un nodo è possibile ottenere il puntatore del nodo chiamando

function TBaseVirtualTree.GetNodeAt(X, Y: Integer; Relative: Boolean;
  var NodeTop: Integer): PVirtualNode;

La coordinata Y di un nodo è la somma delle altezze di tutti i nodi visibili precedenti. Dando per scontato che non si dispone di nodi crollati (quindi o si tratta di una semplice lista di record, o tutti i nodi con i nodi figli sono espanso) e tutti hanno l'altezza di default questo è facile. Questo codice dovrebbe essere un buon punto di partenza:

procedure TForm1.SelectTreeNode(AIndex: integer; ACenterNodeInTree: boolean);
var
  Y, Dummy: integer;
  Node: PVirtualNode;
begin
  Y := Round((AIndex + 0.5) * VirtualStringTree1.DefaultNodeHeight);
  Node := VirtualStringTree1.GetNodeAt(0, Y, False, Dummy);
  if Node <> nil then begin
    Assert(Node.Index = AIndex);
    VirtualStringTree1.ScrollIntoView(Node, ACenterNodeInTree);
    VirtualStringTree1.Selected[Node] := True;
    VirtualStringTree1.FocusedNode := Node;
  end;
end;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top