2009-02-11 12 views
12

Questa è probabilmente una domanda stupida, ma il mio cervello è appena cotto abbastanza Penso che userò una delle mie "linee di vita" per vedere se riesco a ottenere un po 'di aiuto dai miei amici in overflow. ;)Eliminazione di tutti i componenti di una determinata classe in un modulo (Delphi)

Ho bisogno di eliminare tutte le occorrenze di un particolare tipo di componente nel mio modulo principale (alcune di esse sono all'interno di pannelli o fogli di calcolo, ma tutte su e di proprietà dello stesso modulo). Ecco quello che ho adesso:

for i := 0 to frmMain.ComponentCount - 1 do 
    begin 
    if frmMain.Components[i] is TMyClass then frmMain.Components[i].Destroy; 
    end;  

Il problema è (e sapevo che sarebbe stato prima che ho compilato esso) che, una volta distruggo la componente, lista dei componenti re-indici del modulo e finisco fuori dai limiti.

Qual è il modo migliore per risolvere questo problema? Ho pensato di aggiungere i componenti "trovati" a un array standalone, e poi passare attraverso quello dopo questo ciclo per eliminarli, che penso funzionerà .... ma è l'approccio migliore?

TIA


UPDATE:

Voi ragazzi roccia. Grazie. :)

risposta

27

Hai quasi ragione. Il tuo ciclo dovrebbe essere simile

for i := frmMain.ComponentCount - 1 downto 0 do 
begin 
    if frmMain.Components[i] is TMyClass then 
    frmMain.Components[i].Free; 
end; 

In questo modo la chiamata alla funzione "frmMain.ComponentCount" viene fatto all'inizio e non di nuovo.

Dovresti anche chiamare Gratuito come sopra, non Distruggi - Non riesco a ricordare perché al momento. Bri

+4

Destroy è virtuale. Se l'oggetto è stato già distrutto, fallirebbe. Verifica gratis per vedere se ha un riferimento valido prima di chiamare Destroy. Non è probabile che ci sia un problema qui, ma una buona pratica in generale. –

+2

In questo caso, è sicuro chiamare semplicemente Destroy.A causa del modo in cui VCL gestisce questo elenco, non è probabile che vi sia un riferimento non valido in tale elenco. Anche se ci fosse, Free non ti proteggerà perché si basa sull'istanza di essere nullo. –

+2

Si noti inoltre che il ciclo passa da alto a zero, per garantire che tutti gli articoli siano considerati, altrimenti il ​​ciclo può saltare gli elementi accanto a quello cancellato. Importante da non perdere. – mj2008

10

Iniziare in alto e lavorare all'indietro.

cioè:

for i := frmMain.ComponentCount - 1 downto 0 do 
begin 
    if frmMain.Components[i] is TMyClass then frmMain.Components[i].Free; 
end; 

chiamate gratuitamente invece di distruggere. Chiamate gratuite Distruggi dopo aver verificato un riferimento valido.

+1

Egli deve anche chiamata gratuita e non a distruggere. Non si dovrebbe mai chiamare Destroy e chiamare sempre Free. –

1

La stessa soluzione con un ciclo while:

i := 0; 
while i < frmMain.ComponentCount do 
begin 
    if frmMain.Components[i] is TMyClass then 
    frmMain.Components[i].Free 
    else 
    inc(i); 
end; 
+0

questo non funzionerà - (i) sta salendo e (frmMain.ComponentCount) sta scendendo –

+1

Se si dà una seconda occhiata, vedrai che voglio venire se il conto del componente va giù. Se ogni singolo componente è di classe TMyClass, resterei a zero e il ciclo while terminerebbe, perché 0 <0 è falso – Vegar

2

Esso non può avvenire nel tuo caso, ma il controllo if frmMain.Components[i] is TMyClass sarà anche restituire vero per classi discendenti di TMyClass. Se si sta veramente cercando la rimozione di una classe specifica, potrebbe essere necessario aggiungere un ulteriore controllo dello ClassName.

-3

Se avete bisogno di controllare & distruggere un componente noto di nome Usa

If YourComponent <> Nil Then 
    YourComponent.Free; 
+2

Questo è più o meno lo stesso di 'se YourComponent <> nil poi se YourComponent <>. nil poi YourComponent.Destroy; ' Il doppio se non è ** quello ** sensato, vero? :-) –

-2

Per Belle Contrle in forma o il pannello può utilizzare questo codice

var 

i:Integer; 

begin 

for i := 0 to Panel1.ControlCount - 1 do 

    begin 

    if Panel1.Controls[i] is TEdit then 
     Tedit(Panel1.Controls[i]).text := ''; 

    end; 
Problemi correlati