![]() |
Komponente aus Array löschen
Hallo :)
das Thema klingt simpel und wurde z.B. für Arrays of Integer schon sehr oft beantwortet, jedoch stellt es sich nicht ganz so leicht dar, weil meine Elemente initialisierte Komponenten sind. Folgendes Problem: Ich habe in ein dynamisches Array of TShape wobei dessen Elemente während der Laufzeit manuell erstellt werden können. Den Elementen ist ein Popupmenu (Popupmenu2) zugeordnet, welches u.a. zum löschen eines Elements dient. Die Position des Elements im Array, wird dabei über den Tag bestimmt. Nun möchte ich gerne ein Element an einer beliebigen Stelle löschen, wobei alle anderen Elemente im Array aufrücken müssen. Die Lösung über eine List ist aufgrund des restlichen Programmes leider nicht möglich. Hier ein Ansatz der (nicht funktioniert wobei er jedoch) meine Idee verdeutlicht.
Delphi-Quellcode:
Ich hoffe auf eure Hilfe!
[...]
var Form1: TForm1; Btns : Array of TShape; [...] procedure TForm1.Lschen2Click(Sender: TObject); var i, Helper : Integer; begin Helper := Popupmenu2.PopupComponent.Tag; //Wo ist das zu löschende Shape im Array [...] for i := helper to length(btns)-2 do //Alle Elemente um eins vorrücken(Das zu löschende SOLL überschreiben werden) begin btns[i] := btns[i+1]; end; btns[length(btns)-1].Free; //letztes (doppeltes) Element wird gelöscht setlength(btns,length(btns)-1); for i := 0 to length(btns)-1 do btns[i].Tag := 1; // Tag wird wieder Position im Array end; [...] end. lg Flo |
AW: Komponente aus Array löschen
Viele Programmierer versuchen Objekte, Komponenten und Controls in Arrays zu speichern,
obwohl es viel geeignetere Datenstrukturen gibt. Zitat:
Arrays sind low-Level Datenstrukturen. Je anspruchsvoller die gewünschte Funktionalität eines Programms wird umso höherwertiger müssen auch die Datenstrukturen werden. Z.B. bringt die Klasse TComponent schon alles mit was du brauchst.
Delphi-Quellcode:
Wichtig zu wissen: ShapeList wird automatisch freigegeben, wenn das Formular freigegeben wird.
type
TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private-Deklarationen } ShapeList : TComponent; // Liste von Shapes end; procedure TForm1.FormCreate(Sender: TObject); begin ShapeList := TComponent.Create(Self); end; Und ausserdem werden alle Shapes in der Liste ebenfalls automatisch freigegeben. So kann man z.B. ein neues Shape hinzufügen:
Delphi-Quellcode:
Um ein bestimmes Shape anhand des Tag zu finden und zu löschen:
procedure TForm1.Button1Click(Sender: TObject);
var newshape : TShape; begin newshape := TShape.Create(ShapeList); newshape.Left := random(300); newshape.Top := random(300); newshape.Parent := Self; end;
Delphi-Quellcode:
Anstatt in dem Tag des PopupMenue die Position in der Liste zu speichern, kann man auch gleich das Shape selbst speichern.
procedure TForm1.DeleteShapeByTag(ATag:integer);
var c : TControl; i : integer; begin for i := ShapeList.ComponentCount-1 downto 0 do begin c := ShapeList.Components[i]; if c.Tag=ATag then begin // Shape löschen c.Free; // die ShapeList wird im Hintergrund automatisch korrigiert // d.h. ComponentCount verringert sich um eins end; end; |
AW: Komponente aus Array löschen
Danke für die Antwort, jedoch existieren dabei 3 Probleme.
Das erste ist, dass der Code einen sehr wichtigen Fehler enthält, so ist der Rückgabewert an c Zitat:
Zitat:
Fall1: Man löscht Shape mit dem Index 0, dann werden alle Shapes gelöscht. Fall2: Man löscht ein Shape größer als Null, dann passiert nichts. So ... das dritte und das schwerwiegenste Problem ist, dass ich selbst weiß wie es anders geht, jedoch wollte ich wissen wie es mit array funktioniert. PS: Ist nicht böse gemeint, ich hoffe jemand hat noch eine Idee! |
AW: Komponente aus Array löschen
Hallo,
wenn es denn unbedingt mit Arrays sein soll, würde ich so vorgehen: Shape aus dem Ursprungsarray löschen. Position auf nil setzen. Neues Array erstellen mit der Länge des Ursprungsarrays -1. Alle Elemente <> nil in das neue Array kopieren. Ursprungsarray löschen. Grüße Klaus |
AW: Komponente aus Array löschen
Warum mit zwei Arrays arbeiten? Einfach alle nachfolgenden Elemente um eins nach vorne kopieren. Vorher aber das zu löschende Objekt freigeben. Und danach natürlich das Array um ein Element verkürzen.
Muss die Sortierreihenfolge nicht erhalten bleiben, kann man auch das letzte Element an die Stelle des zu löschenden Elementes kopieren. |
AW: Komponente aus Array löschen
Zitat:
Man kann das mit einer Schleife machen. Hardcore - Programmierer setzen hier auch die Procedure Move ein.
Delphi-Quellcode:
Anschliesend musst du wohl auch noch noch die Tag-Werte von deinem Popupmenu korrigieren.
procedure RemoveElementFromArray(a : Array of TShape; idx:integer);
var i : integer; begin Assert(idx >= 0); for i := idx to High(a)-1 do begin a[idx] := a[idx+1]; end; SetLength(a, Length(a)-1); // Array verkürzen end;
Delphi-Quellcode:
Ich kann nur sagen, dass du so einen hässlichen Sourcecode bekommst.
for i := 0 to Popupmenu2.Items.count-1 do
begin if Popupmenu2.Items[i].Tag >= Helper then Popupmenu2.Items[i].Tag := Popupmenu2.Items[i].Tag -1; end; Würdest du meinen Vorschlag annehmen, dann sähe das Löschen so aus:
Delphi-Quellcode:
procedure TForm1.Lschen2Click(Sender: TObject);
var mi : TMenuItem; c : TComponent; begin mi := Sender as TMenuItem; // im Tag des Menuitems steckt die Verbindung zum Shape c := TComponent(mi.Tag); if not Assigned(c) then Exit; c.Free; // Shape wird gelöscht und automatisch auch aus ShapeList entfernt |
AW: Komponente aus Array löschen
@Klaus: Nette Idee aber eher die brachiale methode ^^
@Luckie: Guck dir mal an, was ich gemacht hab. Oder was meinst du? @shima: Vielen Danke, aber bei deinem Vorschlag zum Thema Array, wird das Elemten was zu löschen ist, aus dem Array entfernt, aber nicht gelöscht. Das letzte Element im Array wird auch aus dem Array entfernt, jedoch auch nichts gelöcht. Hab ich mich vielleicht vertippt? Kannst du das bitte selbst probieren ob es bei dir klappt? lg |
AW: Komponente aus Array löschen
.. schon mal überlegt was diese Zeile macht?
Delphi-Quellcode:
Grüße
for i := 0 to length(btns)-1 do btns[i].Tag := 1; // Tag wird wieder Position im Array
Klaus |
AW: Komponente aus Array löschen
Moin moin,
ich würde auch Shimas Methode bevorzugen...
Delphi-Quellcode:
So sollte es aber funktionieren.
type
TShapeArr = Array of TShape; //.. procedure RemoveElementFromArray(var a : TShapeArr; Idx: Integer); var I, x: Integer; begin x := Length(a); if x > 0 then begin Assert((idx >= 0) and (idx < x)); a[idx].Free; for I := Idx to x-2 do begin a[I] := a[Succ(I)]; end; SetLength(a, x -1); end; end; |
AW: Komponente aus Array löschen
Moin,
warum gibst du das letzte Element frei? Nicht der Inhalt sondern die Referenz wird bei der Aktion kopiert. Das heißt die letzten beiden Einträge zeigen (vor den .Free) auf das gleiche Element. Durch das freigeben, wir das letzte Element aber freigegeben und zwar das letzte Element für „beide“ Arrays (also bevor du es verkürzt: Das letzte (was du evtl. willst) und das vorletzte (was du bestimmt nicht willst)). Und warum setzt du den Tag für jedes Shape auf 1? Und auf das Popupmenü bekommt kein neues Tag, soll das so sein? Außerdem gibst du nicht (!) das gelöscht Element frei. Das verschwindet ins Nirvana, weil du einfach die Referenz mit den nachfolgenden Element überschreibst. Das heißt, einfach Luckies Rat folgen und: Zitat:
Zitat:
MfG Fabian |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:44 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz