TImages löschen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
cryptomaniac
Beiträge: 4
Registriert: Sa 24. Mär 2012, 16:23

TImages löschen

Beitrag von cryptomaniac »

Hallo Leute,
hab leider gerade bei meinem Mine-sweper-Projekt ein paar kleine Probleme.
Kurz zum Aufbau: Ich habe ein 2 Dimensionales Array, wo TImages drin sind.
Die eigentliche Logik, also die Objekte die speichern, ob auf dem Feld eine Mine liegt etc. liegen in einem anderen Array, das einer anderen Klasse "gehört".
Jetzt habe ich folgendes Problem: Wenn der Spieler bspw. ein 10*10 Feld erzeugt und spielt, und anschließend ein 3*3 Feld erzeugen will, müssen die 100 Images irgendwie gelöscht werden, damit ich 9 neue erzeugen kann
Ich habe dafür einfach dem Array die Länge 0 zugewiesen und anschließend die Länge 3*3
Leider sind die restlichen 91 Images dann trotzdem noch vorhanden, beim draufklicken gibt es aber (natürlich) einen Absturz.
Wie kann ich diese Images jetzt so löschen,dass sie auch nicht mehr angezeigt werden?

Vielen Dank für eure Hilfe!

euer
Cryptomaniac

u-boot
Beiträge: 308
Registriert: Do 9. Apr 2009, 10:10
OS, Lazarus, FPC: Ubuntu 9.10 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 785..

Re: TImages löschen

Beitrag von u-boot »

Lese über Destroy, Free, FreeAndNil.

Evtl könnte ein zusätzliches invalidate noch helfen.
Ubuntu 9.10 (L 0.9.28 FPC 2.4.x)

cryptomaniac
Beiträge: 4
Registriert: Sa 24. Mär 2012, 16:23

Re: TImages löschen

Beitrag von cryptomaniac »

Danke, für deine Antwort :)
Auf was muss ich das denn anwenden? Auf das Array an sich oder per Schleife auf alle TImages in dem Array?

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: TImages löschen

Beitrag von Antrepolit »

Mir scheint, du denkst da etwas falsch. Um 100 Bilder zu zeichnen, benötigst du keine 100 TImages.
Du brauchst nur eines, dass du 100 mal zeichnest. Anders wäre das Speicherverschwendung, was sehr schlechtes Programmieren ist.
Und das erste Array mit Bildern brauchst du auch nicht. Du musst nur den Inhalt des ersten Arrays am Bildschirm abbilden.
Grüße, Antrepolit

care only if your os is really burning

cryptomaniac
Beiträge: 4
Registriert: Sa 24. Mär 2012, 16:23

Re: TImages löschen

Beitrag von cryptomaniac »

Hmm, also bei mir sind dem Array für jedes Feld tatsächlich ein Image.
Grund ist für mich als Einsteiger gewesen, dass ich dann mittels Schleife jedem Image per Schleife als Namen seine eindeutige Position zuordne. Diese kann ich dann, wenn der Spieler auf das entsprechende Feld klickt auslesen und entsprechend verarbeiten.
Außerdem kann ich so problemlos bei jedem aufdecken eines Feldes das entsprechende Bild aus einer bmp in das Image laden.
Gibt es denn (außer die komplette Struktur zu ändern) keine Möglichkeit die Images von der Anzeige zu löschen?

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: TImages löschen

Beitrag von MAC »

die antwort ist sehr sehr einfach.
Allerdings mit einer struckturänderung wie hier forgeschlagen wäre es noch einfacher :)
Ich helfe dir trotzdem mal auf deinem jetzigen weg.
Wenn du die länge eines Arrays in dem sich OBJEKTE also alles Objektorientierte unter anderem auf Klassen auf 0 setzt. Dann hast du erfolgreich jegliche Spuren die zu diesem Objekt führen verwicht. Das objekt ist noch da. Da du nun aber keine Spur mehr zu deinem Objekt ( = Pointer ) mehr hast, kkönnen diese auch nicht mehr gelöscht werden... Er werden also immer mehr TImages erstellt die beim nächsten Level einfach irgendwo in deinem Ram versteckt werden. Oder anders ausgedrückt dein Programm brauch immer mehr und mehr und mehr Speicher (= Speicherleg).
Deswegen müssen alle Objekte gelöscht werden.
Am besten machst du das mit TObject.Free; Nachdem du ein Objekt gelöscht hast solltest du noch die Variable auf nil setzen (nicht ZWINGEND notwendig, aber guter programmierstil) die Procedure FreeAndNil macht beides gleichzeitig...
Also ganz kurz und knapp

Code: Alles auswählen

for i := 0 to high(meinarray) do
begin
FreeAndNil(meinarray[i])
end
setlength(meinarray,0)

Code: Alles auswählen

Signatur := nil;

cryptomaniac
Beiträge: 4
Registriert: Sa 24. Mär 2012, 16:23

Re: TImages löschen

Beitrag von cryptomaniac »

Code: Alles auswählen

procedure TForm1.RemoveButs; //löscht das Array
var i,j:Integer;
begin
  if buts<> NIL then
  begin
  for i:= 0 to high(buts) do
           begin
           for j:= 0 to high(buts[i]) do
               begin
                freeandnil(buts[i,j]);
                buts[i,j]:=nil
               end;
           end;
  end;
  setLength(buts,0,0);
end;
So, das ist meine Methode. Buts ist als array of array of Timage definiert.
Leider werden die Images nach dem Löschen trotzdem noch angezeigt, nur Sie sind nicht mehr klickbar sondern werfen einen Fehler...
Hast du noch eine Idee was ich falsch gemacht habe?

Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: TImages löschen

Beitrag von theo »

Ich würde das ganz anders machen.
Das ist ja ein Schachbrettmuster, oder? Da brauchst du eigentlich keine Positionen speichern, es genügt eine eine einfache Berechnung.
Dann zeichnest du die Felder in OnPaint auf das Control oder die TForm und hast mit tonnenweise Objekten createn und destroyen nichts zu tun.
Mausereignisse kannst du über die selbe Rechnung einem Feld zuweisen.

z.B. so. Wenn du das in OnPaint einer Form ausführst, kriegst du ein Schachbrettmuster.
Dabei kannst du nat. statt einer Farbe auch ein Bitmap zeichnen evtl. anhand eines einfachen Array of Boolean bestimmt.
Das Beispiel ist kurz, damit das Wesentliche klar wird. Am Besten machst du eine Klasse.

Code: Alles auswählen

procedure TForm1.FormPaint(Sender: TObject);
var
  lines, i,  w, h, padding, offset: integer;
 
  function _getRect(num: integer): TRect;
  begin
    Result.Left := num mod Lines * (w + padding) + offset;
    Result.Top := num div Lines * (h + padding) + offset;
    Result.Right := Result.Left + w;
    Result.Bottom := Result.Top + h;
  end;
 
begin
  lines := 7;
  padding := 2;
  offset := 10;
  w := 20;
  h := 20;
  for i := 0 to sqr(lines) - 1 do
  begin
    if odd(i) then
      Canvas.Brush.Color := clred
    else
      Canvas.Brush.Color := clyellow;
    Canvas.Rectangle(_getRect(i));
  end;
end;

Antworten