Autor |
Beitrag |
idefix123456
      
Beiträge: 23
|
Verfasst: Sa 16.07.11 15:29
Hallo,
Ich bin hier langsam am verzweifeln ich habe jetzt schon ethliches ausprobiert, und erhalte Ständig bei meinem Code Fehlermeldungen die ich mir einfach nicht erklären kann.
Es geht darum, ich Erstelle mehrere Dynamische Bilder mit der class TMyImage. Diese Bilder werden auf der Form angezeigt und zusätzlich mit der unteren Procedure in einer TObjectList gespeichert!
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| var ObjectList: TObjectList; ObjectListCreated: boolean = false;
procedure ObjectList_Push(MyImage: TMyImage); begin
if not ObjectListCreated then begin
ObjectList := TObjectList.Create; try ObjectList.Add(MyImage); ObjectListCreated := true; except ObjectList.free; end;
end else ObjectList.Add(MyImage);
end; |
Das Speichern funktioniert auch Ohne Probleme das habe ich schon Getestet!
Jetzt sollen aber ALLE Objekte aus der TObjectList gelöscht werden. AUßER die, dessen Namen im einem Array Stehen...
Folgender Code mit ShowMessage Funktioniert! Das ShowMessage zeigt genau die Objekte.Namen an, die gelöscht werden sollen!
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| var i: integer; img: TMyImage; arr: array of TMyImage;
...
if ObjectListCreated then begin
for i := ObjectList.Count-1 downto 0 do begin
img := (ObjectList.Items[i]) as TMyImage;
if not array_In(NichtLoeschen, img.Name) then begin
ShowMessage(img.Name);
end;
end;
end; |
Sobald ich mich aber nun an das Löschen wage, erhalte ich verschiedene fehler. Ich habe alle mal zusammengeschrieben.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| var arr: array of TMyImage;
...
if ObjectListCreated then begin
for i := ObjectList.Count-1 downto 0 do begin
img := (ObjectList.Items[i]) as TMyImage;
if not array_In(NichtLoeschen, img.Name) then begin
ObjectList.Delete(i); ObjectList.Remove(img);
ObjectList.Remove(ObjectList.Items[i]);
int := Length(arr); SetLength(arr, int + 1); arr[int] := img;
end;
end;
for i := 0 to Length(arr)-1 do begin
ObjectList.Remove(arr[i]);
end;
end; |
Langsam weis ich nichtmehr Weiter. Sobald ein Objekt gelöscht werden soll, jammert er mit den ganzen Fehlern rum. Wo ich mir aber selbst nicht erklären kann, warum er überhaupt jammert. Alle Objekte die er Löschen soll existieren schließlich, wie das ShowMessage ja beweist!
Und Laut ethlichen Quellen bei google ist das ObjectList.Remove bzw ObjectList.Delete die beste möglichkeit ein Objekt aus einer ObjectList zu Löschen...
Wer kann helfen? Währe dankbar über eine Antwort...
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 16.07.11 18:48
idefix123456 hat folgendes geschrieben : | Hallo,
Ich bin hier langsam am verzweifeln ich habe jetzt schon ethliches ausprobiert, und erhalte Ständig bei meinem Code Fehlermeldungen die ich mir einfach nicht erklären kann.
Es geht darum, ich Erstelle mehrere Dynamische Bilder mit der class TMyImage. Diese Bilder werden auf der Form angezeigt und zusätzlich mit der unteren Procedure in einer TObjectList gespeichert! |
Schauen wir doch mal der Reihe nach...
idefix123456 hat folgendes geschrieben : | Delphi-Quelltext 1: 2: 3:
| var ObjectList: TObjectList; ObjectListCreated: boolean = false; | |
Ich würde hier nur genau eine Variable ObjectList einsetzen und den Status, ob die Liste initialisiert ist mit der Funktion Assigned abfragen.
Delphi-Quelltext 1: 2:
| var ObjectList: TObjectList = nil; |
idefix123456 hat folgendes geschrieben : | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure ObjectList_Push(MyImage: TMyImage); begin
if not ObjectListCreated then begin
ObjectList := TObjectList.Create; try ObjectList.Add(MyImage); ObjectListCreated := true; except ObjectList.free; end;
end else ObjectList.Add(MyImage);
end; | |
Diese Funktion macht relativ wenig Sinn in ihrer jetzigen Form. Verkürzt steht da: Wenn die Liste nicht existiert, lege sie an und gebe sie sofort wieder frei, wenn das erste Bild nicht eingefügt werden kann. Dabei setzt Du aber den Status, dass die Liste freigegeben wurde nicht. Besser wäre hier etwa Folgendes:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure ObjectList_Push(MyImage: TMyImage); begin if not Assigned(ObjectList) then begin try ObjectList := TObjectList.Create; except FreeAndNil(ObjectList); raise; end; end;
ObjectList.Add(MyImage); end; |
Oder anders ausgedrückt: Wenn die ObjectList nicht existiert, versuche sie anzulegen. Tritt dabei ein Fehler auf, stelle sicher, dass die Variable auf nil steht und schmeiße den Fehler zur Behandlung erneut. Dadurch wird auch die Routine verlassen.
Für den Fall, dass wir bereits eine Liste haben, füge einfach das Bild hinzu.
Beachte auch die von mir als Kommentar eingefügte Zeile bzgl. ObjectList.OwnsObjects := False;. Diese ist u.U. nötig, um das doppelte Freigeben von Objekten zu vermeiden.
idefix123456 hat folgendes geschrieben : | Das Speichern funktioniert auch Ohne Probleme das habe ich schon Getestet! |
Ganz sauber sah das Speichern nun nicht grad aus
idefix123456 hat folgendes geschrieben : | Jetzt sollen aber ALLE Objekte aus der TObjectList gelöscht werden. AUßER die, dessen Namen im einem Array Stehen...
Folgender Code mit ShowMessage Funktioniert! Das ShowMessage zeigt genau die Objekte.Namen an, die gelöscht werden sollen!
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| var i: integer; img: TMyImage; arr: array of TMyImage;
...
if ObjectListCreated then begin
for i := ObjectList.Count-1 downto 0 do begin
img := (ObjectList.Items[i]) as TMyImage;
if not array_In(NichtLoeschen, img.Name) then begin
ShowMessage(img.Name);
end;
end;
end; | |
Auch hier kurz einmal die Korrektur von oben um auf die neue Semantik mit der Objekt-Liste einzugehen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| var i: integer; img: TMyImage; arr: array of TMyImage;
...
if Assigned(ObjectList) then begin for i := ObjectList.Count-1 downto 0 do begin img := (ObjectList.Items[i]) as TMyImage; if not array_In(NichtLoeschen, img.Name) then begin ShowMessage(img.Name); end; end; end; |
idefix123456 hat folgendes geschrieben : | Sobald ich mich aber nun an das Löschen wage, erhalte ich verschiedene fehler. Ich habe alle mal zusammengeschrieben.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| var arr: array of TMyImage;
...
if ObjectListCreated then begin
for i := ObjectList.Count-1 downto 0 do begin
img := (ObjectList.Items[i]) as TMyImage;
if not array_In(NichtLoeschen, img.Name) then begin
ObjectList.Delete(i); ObjectList.Remove(img);
ObjectList.Remove(ObjectList.Items[i]);
int := Length(arr); SetLength(arr, int + 1); arr[int] := img;
end;
end;
for i := 0 to Length(arr)-1 do begin
ObjectList.Remove(arr[i]);
end;
end; | |
Hier gibt es nun zwei Probleme, die Du beachten musst. Eines habe ich oben ja bereits angedeutet, das andere ist die Reihenfolge:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| var arr: array of TMyImage;
...
if Assigned(ObjectList) then begin for i := ObjectList.Count-1 downto 0 do begin img := (ObjectList.Items[i]) as TMyImage;
if not array_In(NichtLoeschen, img.Name) then begin ObjectList.Remove(img); end; end; end; |
Kannst Du hier kurz mal von TMyImage kurz die Deklaration geben?
idefix123456 hat folgendes geschrieben : | Langsam weis ich nichtmehr Weiter. Sobald ein Objekt gelöscht werden soll, jammert er mit den ganzen Fehlern rum. Wo ich mir aber selbst nicht erklären kann, warum er überhaupt jammert. Alle Objekte die er Löschen soll existieren schließlich, wie das ShowMessage ja beweist!
Und Laut ethlichen Quellen bei google ist das ObjectList.Remove bzw ObjectList.Delete die beste möglichkeit ein Objekt aus einer ObjectList zu Löschen... |
Achte bitte demnächst etwas auf deine Rechtschreibung. Habe zuerst "laut ethischen Quellen" gelesen und mich gewundert, was die Herkunft und Gebräuche von Objekten mit diesem Problem zu tun haben.
idefix123456 hat folgendes geschrieben : | Wer kann helfen? Währe dankbar über eine Antwort... |
Hoffe, das ganze hilft. Ansonsten geh mal im Einzelschritt durch deinen Quelltext und schau, was genau er da versucht zu tun.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
idefix123456 
      
Beiträge: 23
|
Verfasst: Sa 16.07.11 19:56
Hallo,
Danke für deine Ausführliche Antwort. Leider bringen die von dir genannten Änderungen keine Verbesserung.
Ich bekomme jetzt mit dieser Konstellation leider jedesmal einen Fehler, wenn versucht wird die Images zu Löschen
Delphi-Quelltext 1: 2: 3: 4:
| ObjectList.Remove(img); |
und wenn ich das so schreibe
Delphi-Quelltext 1: 2: 3: 4:
| ObjectList.Remove(img); FreeAndNil(img);
|
Außerdem wird wenn ich das...
Delphi-Quelltext 1:
| ObjectList.OwnsObjects := false; |
...setze, garnichtsmehr gelöscht!
Die Deklaration von TMyImage ist nichts Weltbewegendes, ich habe lediglich eine Variable Filename hinzugefügt
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| TMyImage = class(TImage) private Filename: string; public end; |
Das Bild wird so erstellt...
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90:
| procedure dyn_Image(form: TObject; dateiname: string; ImgLeft, ImgTop: integer; imgname: string = 'false'); var MyImage: TMyImage; ValidImage: boolean; begin
if FileExists(ExtractFilePath(Application.ExeName) + '\img\' + dateiname) then begin
if ObjectList_CheckIdentic(dateiname, ImgLeft, ImgTop) = 'false' then begin
if imgname = 'false' then begin
i := i + 1; imgname := 'dynImage' + inttostr(i);
end else dyn_Delete(imgname);
ValidImage := false;
MyImage := TMyImage.Create(TComponent(form)); try
MyImage.Picture.LoadFromFile(ExtractFilePath(Application.ExeName) + '\img\' + dateiname);
MyImage.Filename := dateiname;
MyImage.Left := ImgLeft; MyImage.Top := ImgTop;
MyImage.Transparent := true; MyImage.Visible := true; MyImage.Parent := TWinControl(form); MyImage.BringToFront;
MyImage.Stretch := false; MyImage.Proportional := false;
MyImage.AutoSize := true;
MyImage.Name := imgname;
ValidImage := true;
except
MyImage.Free;
end;
if ValidImage then begin ObjectList_Push(MyImage);
if BildNichtLoeschen then NichtLoeschen_Push(imgname);
end;
end else begin
if BildNichtLoeschen then NichtLoeschen_Push(ObjectList_CheckIdentic(dateiname, ImgLeft, ImgTop));
end; end else ShowMessage('Fehler: Bild "' + dateiname + '" konnte nicht gefunden werden!');
end; |
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 16.07.11 20:06
Okay, dein Code für das Erstellen zeigt den Fehler
Und zwar setzt Du in Zeile 29 den Owner der Images auf die Form, Default bei der ObjectList ist aber auch das Freigeben der Objekte beim Entfernen aus der Liste.
Nun gibt es hier drei Ansätze zu verfolgen:
1. Alle Bilder in Obhut der ObjectList geben, was in Anbetracht der Vermengung mit der VCL recht problematisch werden dürfte
2. Alle Bilder nur dem Formular zuordnen, was allerdings bedeutet, dass Du Verwaltungs-Source für das Entfernen der visuellen Komponente schreiben musst
3. Die Images unabhängig von deinem Formular und deiner Objekt-Liste selber verwalten. Das ist zwar der größte Aufwand, ist aber mit am saubersten, da so klar ersichtlich wird, wo sich wer um die Speicherverwaltung kümmert.
In jedem Fall musst Du das Image vor dem Löschen/Freigeben durch Zuweisen von img.Parent := nil; vom Formular entfernen, da es sonst noch als Komponente dort verwaltet wird. Daher die Fehlermeldung wegen einer ungültigen Zeigeroperation.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
idefix123456 
      
Beiträge: 23
|
Verfasst: Sa 16.07.11 21:35
Hallo,
ja ich werde es mal Versuchen aber mir ist jetzt Folgendes nicht klar...
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| if Assigned(ObjectList) then begin for i := ObjectList.Count-1 downto 0 do begin img := (ObjectList.Items[i]) as TMyImage;
if not array_In(NichtLoeschen, img.Name) then begin
ObjectList.Remove(img); img.Parent := nil; img.Free;
end; end; end; |
... So sollte doch eigentlich Das Image aus der ObjectList und von der Form gelöscht werden. Stattdessen erhalte ich wieder den altbekannten Fehler listenindex oder ungültiger pointer
Kann man nicht auch Anstatt der ObjectList einfach nur eine art Handle des Dynamischen Bildes Übergeben. Eine Rießen ObjectList die die Bilder quasi nochmal speichert zusätzlich zu dem was auch schon in der VCL form1 vorhanden ist, ist ja eh überflüssig, ich bräuchte ja nur eine art Handle um später einfach über Object.Free das ganze von der Form wieder entfernen zu können.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 16.07.11 22:17
Die Änderung bzgl. TMyImage.Create(nil) beim Erzeugen hattest Du beachtet?
Hab leider kein Delphi grad da, um das zu testen.
Edit: Ach ja, fällt mir grad noch auf: Bei deiner Funktion zum Erzeugen übergibst Du form: TObject, erwartest weiter unten aber Form mindestens von TWinControl abgeleitet. Wenn Dir jemand ein Objekt übergibt, was nicht von TWinControl abgeleitet ist, knallt es. Besser wäre hier bereits in der Deklaration mindestens TWinControl anzugeben; in deinem Fall aber eher sogar TForm oder TCustomForm. Der Type Cast in Zeile 46 entfällt dann.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
idefix123456 
      
Beiträge: 23
|
Verfasst: So 17.07.11 15:00
Hallo,
Ich bekomme es einfach nicht hin, jetzt habe ich den Kompletten Code umgestellt. Ich habe die ObjectList entfernt und wollte nun die Objekte auf der Form Finden. Aber was ist, ich erhalte dennoch mal wieder den altbekannten Fehler: "Listenindex Überschreitet das maximum".
Das Bild wird jetzt so Dynamisch erzeugt...
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76:
| procedure dyn_Image(dateiname: string; ImgLeft, ImgTop: integer; imgname: string = 'false'); var str: string; begin
if FileExists(ExtractFilePath(Application.ExeName) + '\img\' + dateiname) then begin
str := CheckIdentic(dateiname, ImgLeft, ImgTop);
if str = 'false' then begin
if imgname = 'false' then begin
z := z + 1; imgname := 'dynImage' + inttostr(z);
end else dyn_Delete(imgname);
with TMyImage.Create(Form1) do try
Picture.LoadFromFile(ExtractFilePath(Application.ExeName) + '\img\' + dateiname);
Filename := dateiname;
Left := ImgLeft; Top := ImgTop;
Transparent := true; Visible := true; Parent := Form1; BringToFront;
Stretch := false; Proportional := false;
AutoSize := true;
Name := imgname;
if DeleteNot then DeleteNot_Push(imgname);
except
Free;
end;
end else begin
if DeleteNot then DeleteNot_Push(str);
end; end else ShowMessage('Fehler: Bild "' + dateiname + '" konnte nicht gefunden werden!');
end; |
Will ich nun ein bestimmtes Bild von der Form Löschen, so soll mit dem neuen Code nun einfach die Form durchsucht, und und so das Entsprechende Element gefunden werden! und dieses Eben gelöscht werden!
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| for i := Form1.ComponentCount-1 downto 0 do begin
if Form1.Components[i] is TMyImage then begin
if (TMyImage(Form1.Components[i]) <> nil) then begin
if not array_In(DeleteNotListe, TMyImage(Form1.Components[i]).Name) then begin
TMyImage(Form1.Components[i]).Free;
end;
end;
end;
end; |
Auch wie zuvor Liefert ein ShowMessage die Korrekten Objecte zum Löschen zurück...
Langsam weis ich nichtmehr weiter... Es muss doch möglich sein, ein Simples Bild von der Form zu Löschen, ohne das ich mit Fehlermeldungen bombardiert werde.
EDIT: Außerdem muss ich TMyImage.Create(Form1) anstatt TMyImage.Create(nil) setzen, da sonst der Code zum Suchen auf der Form garnichts findet!
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 18.07.11 05:27
Da fällt mir auf Anhieb nur ein, dass du in TMyImage irgendetwas durcheinander bringst.
Kannst du das Projekt bzw. ein abgespecktes Beispielprojekt einfach einmal anhängen?
idefix123456 hat folgendes geschrieben : | EDIT: Außerdem muss ich TMyImage.Create(Form1) anstatt TMyImage.Create(nil) setzen, da sonst der Code zum Suchen auf der Form garnichts findet! |
Richtig, denn durch die Angabe des Owners wird das Image in das Components-Array eingetragen. Dadurch wird das Image von diesem Owner, hier also dem Formular verwaltet und sollte nie manuell freigegeben werden. Denn das passiert dann automatisch beim Beenden.
Wenn man das Image selbst verwalten und auch freigeben möchte, sollte man immer nil als Owner übergeben, damit es gar nicht erst in das Components Array gelangt.
|
|
|