Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Objekte zur Laufzeit erstellen und löschen (https://www.delphipraxis.net/73099-objekte-zur-laufzeit-erstellen-und-loeschen.html)

bwolf 12. Jul 2006 11:55


Objekte zur Laufzeit erstellen und löschen
 
Hi all,

hab ein kleines Problemchen, wo ihr mir hoffentlich weiterghelfen könnt.

Ich hab eine Form, ein Panel, und 2 Buttons.
Button1 erstellt 10 Objekte auf dem Panel.
Button2 soll diese 10 Objekte wieder entfernen.

Hier der Code:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var cb : TCheckBox;
     intI : integer;
begin
  intI := 0;
  while intI < 9 do
  begin
      cb := TCheckBox.Create(self);
      intI := intI + 1;
      cb.Name := 'test'+intTOSTr(inti);
      cb.Visible := true;
      cb.Parent := Panel1;
      cb.Top := intI*20;
  end;
end;


procedure TForm1.Button2Click(Sender: TObject);
var
  i : integer;
begin
  i := 0;
  while i < Panel1.ControlCount do
  begin
      showmessage(Panel1.Controls[i].name);
      Panel1.Controls[i].free;
      Application.ProcessMessages;
      i := i+1;
  end;
end

Das seltsame ist, das nicht alle Checkboxen entfernt werden, sonder nur jede 2.
Wenn ich mir allerdings nur die Namen anzeigen lasse, und die Checkboxen nicht lösche, werden alle ausgegeben :gruebel:


Danke für eure Hilfe,
grüße Ben

mbamler 12. Jul 2006 11:59

Re: Objekte zur Laufzeit erstellen und löschen
 
versuch es mal mit soetwas wie:
Delphi-Quellcode:
for i := Panel1.ControlCount downto 0 do
begin
    showmessage(Panel1.Controls[i].name);
    Panel1.Controls[i].free;
    Application.ProcessMessages;
end;
Gruß
Matthias

[edit=SirThornberry]Delphi-Tags ergänzt. Nächstes mal bitte selbst setzen. Mfg, SirThornberry[/edit]

jbg 12. Jul 2006 12:03

Re: Objekte zur Laufzeit erstellen und löschen
 
Zitat:

Zitat von bwolf
Delphi-Quellcode:
begin
  intI := 0;
  while intI < 9 do
  begin
      cb := TCheckBox.Create(self);
      intI := intI + 1;

Schon mal was von "for intI := 0 to 8 do" gehört?

Zitat:

Delphi-Quellcode:
begin
  i := 0;
  while i < Panel1.ControlCount do
  begin
      showmessage(Panel1.Controls[i].name);
      Panel1.Controls[i].free;
      Application.ProcessMessages;
      i := i+1;
  end;
end

Zitat:

Das seltsame ist, das nicht alle Checkboxen entfernt werden, sonder nur jede 2.
Aber genau das sagst du dem Compiler, dass er das so machen soll.

Du musst deinen Code nur einmal für zwei Checkboxen durchspielen:
Mit dem ersten Panel1.Controls[i].Free löscht du das 0. Control. Das 1. Control rückt nun auf den Platz des 0. Controls, das 2. auf den des 1., ....
Nun erhöhst du i um eins und löscht danach das 1. Control. Es gibt aber bereits ein neues 0. Controls, das du nun auslässt.

Entweder lässt du das erhöhen von i weg, oder durchäufst die Controls von Count-1 bis 0.
Delphi-Quellcode:
while Panel1.ControlCount > 0 do
  Panel1.Controls[0].Free;

Das Application.ProcessMessages sollte man vorsichtig einsetzen, denn es kann leicht zu einem ungewollten Programmablauf führen, wenn der Benutzer dazwischenfunkt.

bwolf 12. Jul 2006 12:10

Re: Objekte zur Laufzeit erstellen und löschen
 
Hi,

grmpf hab ich d*pp nicht dran gedacht :wall:
Vielen Dank für die aufschlusreiche Antwort!

greets,
ben

Christian18 12. Jul 2006 12:55

Re: Objekte zur Laufzeit erstellen und löschen
 
Hallo,

noch einen Tipp:

dies :

intI := intI + 1;

könntest du durch

Inc(intI);

ersetzen. :-D

himitsu 12. Jul 2006 13:13

Re: Objekte zur Laufzeit erstellen und löschen
 
Zitat:

Zitat von Christian18
Inc(intI);

Och, is garnicht so wichtig ... die Compileroptimierung macht sowas auch automatisch ... man kann also das nehmen, was einem am besten gefällt :)


Wenn man will geht ja och :roll:
Delphi-Quellcode:
intI := Succ(intI);

Christian18 12. Jul 2006 13:23

Re: Objekte zur Laufzeit erstellen und löschen
 
Ja ok hast recht!

es ich eh geschmackssache. ich finde es immer besser wenn der Quellcode übersichtlich ist. Und die Übersichtlichkeit erreicht man meiner Meinung mach mit Funktionen wie diese.

Naja, wie schon gesagt ist geschmakssche. Aber das ich auf jeden Fall machen würde ist folgendes.

Delphi-Quellcode:
for i:=0 to 999 do
  begin

  end;
Dann braucht man auf gar keinen Fall Inc(zahl) oder zahl:=zahl + 1; :lol: :lol: :lol:



MFG Christian18

Peinhard 12. Jul 2006 18:17

Re: Objekte zur Laufzeit erstellen und löschen
 
Wichtig ist auf jeden Fall, beim 'wegwuschen' der Inhalte irgendeiner Auflistung immer 'von hinten' vorzugehen, also mit
Delphi-Quellcode:
for i:=pred(Count) downto 0 do
(wie ja hier auch schon jemand schrob) - sonst passiert auch mit einer for-Schleife das gleiche, was jbg schon schilderte und noch zusätzlich garniert mit lustigen Zugriffsverletzungen bzw Exceptions ('überschreitet das Maximum der Liste') wenn man 'über die Hälfte' ist, da im Unterschied zur while-Schleife die Bedingung 'oben' nicht bei jedem Durchgang neu geprüft wird sondern stur bis zum dem pred(Count) durcheiert, der bei Eintritt in die Schleife mal aktuell war - was sie eben andererseits auch 'effektiver' macht als while-Schleifen mit eigenem inc().

Khabarakh 12. Jul 2006 19:08

Re: Objekte zur Laufzeit erstellen und löschen
 
Auch eine while-Schleife würde nichts ändern. Es wird zwar keine Exception ausgelöst, aber lediglich jedes zweite Item gelöscht.

Peinhard 12. Jul 2006 20:25

Re: Objekte zur Laufzeit erstellen und löschen
 
Zitat:

Zitat von Khabarakh
Auch eine while-Schleife würde nichts ändern. Es wird zwar keine Exception ausgelöst, aber lediglich jedes zweite Item gelöscht.

Das hab' ich so pauschal auch nicht behauptet - der Punkt war, 'von hinten' vorzugehen. Wenn man das macht, funktioniert's auch und sogar mit 'ner while-Schleife:

Delphi-Quellcode:
i := pred(Count);
while i >= 0 do
begin
  wuschweg(i);
  dec(i);
end;
Sie bleibt allerdings gegenüber der for-Schleife zweite Wahl weil wie gesagt ineffektiver - und auch noch mehr Schreibkram...

Khabarakh 12. Jul 2006 20:37

Re: Objekte zur Laufzeit erstellen und löschen
 
Zitat:

Zitat von Peinhard
Zitat:

Zitat von Khabarakh
Auch eine while-Schleife würde nichts ändern. Es wird zwar keine Exception ausgelöst, aber lediglich jedes zweite Item gelöscht.

Das hab' ich so pauschal auch nicht behauptet

Aber auch nicht verneint, also habe ich verneint ;) .

Es gäbe auch noch eine Alternative, bei der die Schleifenrichtung irrelevant ist, allerdings auch wieder etwas ineffektiver:
Delphi-Quellcode:
for i := 0 to List.Count - 1 do
  ThrowIntoGarbage(List[0]);
[edit]Entspricht der Lösung von jbg weiter oben. [/edit]

PS: Das halte ich für einen groben Designfehler in der VCL. Mit einer einfachen Control-Collection-Klasse würde ein "Controls.Clear" genügen und alle wären zufrieden.

Sir Rufo 12. Jul 2006 20:42

Re: Objekte zur Laufzeit erstellen und löschen
 
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
begin
  while Panel1.ControlCount > 0 do
  begin
      showmessage(Panel1.Controls[0].name);
      Panel1.Controls[0].free;
      Application.ProcessMessages;
  end;
end
Was haltet ihr denn von dieser Lösung ... :mrgreen:

Da braucht kein Compiler irgendwas optimieren und die Diskussionen werden gespart :mrgreen:

cu

Oliver

Peinhard 12. Jul 2006 21:07

Re: Objekte zur Laufzeit erstellen und löschen
 
Zitat:

Zitat von Khabarakh
Zitat:

Zitat von Peinhard
Das hab' ich so pauschal auch nicht behauptet

Aber auch nicht verneint, also habe ich verneint ;) .

Aber die pauschale Verneinung ist ja auch wieder nicht richtig! :bouncing4:

Und dein sowie das Beispiel von Rufo Sir zeigt zu allem Überfluss auch noch, daß es doch 'von vorne' geht, und zwar sowohl mit while als auch mit for. Halten wir doch für die interessierte Nachwelt fest, daß man von vorne nie das 'i-te', sondern immer nur das '0-te' Element wegwuschen darf - am effektivsten aber ist und bleibt for 'von hinten', da sich die Liste dabei nicht ständig neu justieren muß und keine while-Bedingung bei jedem Durchlauf neu geprüft werden muß. :warn:

Feierabend! :stupid:

Muetze1 12. Jul 2006 23:57

Re: Objekte zur Laufzeit erstellen und löschen
 
Zitat:

Zitat von Sir Rufo
Da braucht kein Compiler irgendwas optimieren und die Diskussionen werden gespart :mrgreen:

Das ist aber von der Ausführungsgeschwindigkeit die langsamste Variante, da er so mit jedem gelöschten Element erstmal alle nachfolgenden Elemente eins nach vor schieben muss. Dieser Weg ist am uneffektivsten. Wenn, dann so und es läuft auch schnell ab:

Delphi-Quellcode:
  while Panel1.ControlCount > 0 do
  begin
    showmessage(Panel1.Controls[Pred(Panel1.ControlCount)].name);
    Panel1.Controls[Pred(Panel1.ControlCount)].free;
    Application.ProcessMessages;
  end;
/EDIT: Hat Peinhard ja doch schon erwähnt...


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz