AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Undo Redo: Bilder

Ein Thema von R56 · begonnen am 8. Mai 2012 · letzter Beitrag vom 9. Mai 2012
Antwort Antwort
R56

Registriert seit: 8. Mai 2012
8 Beiträge
 
#1

Undo Redo: Bilder

  Alt 8. Mai 2012, 18:27
Also ich hab ein Programm geschrieben, dass mit einem Canvas auf ein Bild schreibt.
Jetzt wollte ich bei jedem schreiben das Bild davor in einem dynamischen Array speichern.
Sobald das Ende erreicht ist, soll der Button abgestellt werden.
Leider komme ich da etwas durcheinander.
Mein Code bisher:
Delphi-Quellcode:
//Auf das Bild schreiben
procedure TForm1.BT_WriteClick(Sender: TObject);
var i,z,x,y: integer;
begin
  SetLength(Bitmap2, High(Bitmap2) + 1);
  Bitmap2[High(Bitmap2)] := TPicture.Create;
  Bitmap2[High(Bitmap2)].Bitmap.Assign(Image1.Picture);
  inc(Bitmap2X);
...
...
end;

//Undo, Redo
procedure TForm1.BT_UndoClick(Sender: TObject);
begin
  if Bitmap2X > Low(Bitmap2) then
    begin
      Image1.Picture.Bitmap.Assign(Bitmap2[Bitmap2X-1]);
      Bitmap2X := Bitmap2X - 1;
    end
  else
    BT_Undo.Enabled := false;
end;

procedure TForm1.BT_RedoClick(Sender: TObject);
begin
  if Bitmap2X < High(Bitmap2) then
    begin
      Image1.Picture.Bitmap.Assign(Bitmap2[Bitmap2X]);
      Bitmap2X := Bitmap2X + 1;
    end
  else
    BT_Redo.Enabled := false;
end;
Wenn das Fenster geschlossen wird:
Delphi-Quellcode:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var i: integer;
begin
for i := Low(Bitmap2) to High(Bitmap2) do
Bitmap2[i].Free;
end;
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.542 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Undo Redo: Bilder

  Alt 8. Mai 2012, 18:31
Hallo und Willkommen in der DP ,

an Deiner Stelle würde ich nicht TPictures in einem Array, sondern gleich TBitmaps in einer TObjectList ablegen. Dazu noch ein privates Feld für den aktuellen Index innerhalb der Objektliste, dann kannst Du vorwärts oder rückwärts in der Liste navigieren.

[edit]
Zitat:
SetLength(Bitmap2, High(Bitmap2) + 1);
Kann es sein, dass Du High mit Length verwechselt hast? [/edit]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen

Geändert von DeddyH ( 8. Mai 2012 um 18:36 Uhr)
  Mit Zitat antworten Zitat
R56

Registriert seit: 8. Mai 2012
8 Beiträge
 
#3

AW: Undo Redo: Bilder

  Alt 8. Mai 2012, 18:37
Ich glaube, der Quellcode würde dann nur unnötig länger als zuvor. Oder?

PS: Kann sein...
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.542 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Undo Redo: Bilder

  Alt 8. Mai 2012, 18:38
Wohl eher verkürzen: Bitmap erzeugen und mit Add der Liste hinzufügen. Bei Programmende dann einfach die Liste freigeben, die kümmert sich per Default um die Freigabe der enthaltenen Objekte.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.024 Beiträge
 
Delphi 12 Athens
 
#5

AW: Undo Redo: Bilder

  Alt 8. Mai 2012, 18:39
Delphi-Quellcode:
//Auf das Bild schreiben
procedure TForm1.BT_WriteClick(Sender: TObject);
var i,z,x,y: integer;
begin
  SetLength(Bitmap2, Length(Bitmap2) + 1); // hier muss es Length heißen!
  Bitmap2[High(Bitmap2)] := TPicture.Create;
  Bitmap2[High(Bitmap2)].Bitmap.Assign(Image1.Picture);
  inc(Bitmap2X);
...
...
end;
An dieser Stelle hängst du zwar das neue Bild an das Ende des Arrays dran, aber wer sagt dir denn, daß Bitmap2X auch wirklich am Ende des Arrays steht?

Für eine saubere Undo/Redo-Implementierung brauchst du zwei Stacks: einen für die Undo- und einen für die Redo-Operation.

Ich habe da mal vor ein paar Jahren etwas geschrieben, das du ja mal als Anregung anschauen kannst: UndoManager
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
R56

Registriert seit: 8. Mai 2012
8 Beiträge
 
#6

AW: Undo Redo: Bilder

  Alt 8. Mai 2012, 21:50
Okay ich wollte es jetzt mit TObjectList probieren, jedoch stoße ich schon auf ein Problem.
Dieser Begriff wäre undeklariert. Über eine Unit, die ich unter den uses benutzen muss hab ich nichts gefunden.

Ps: Hab die Unit.

Pss: Okay, habe jetzt eine Version mit ObjectList und das mit dem Array. Ich habe bei beiden immernoch die selben Probleme wie vorher. Ich weiß nicht wie ich im Index rumschieben soll. Kann mir das jemand bei meinenm Beispil oben zeigen? Ich komm da irgendwie immernoch durcheinander.

Geändert von R56 ( 8. Mai 2012 um 22:48 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.166 Beiträge
 
Delphi 12 Athens
 
#7

AW: Undo Redo: Bilder

  Alt 9. Mai 2012, 02:56
Ob nun ein Array mit vielen Objekten oder eine TList/TObjectList mit vielen Objekten, das macht grundsätlich keinen Unterschied.
Das ist ja nur die Art, wie die Objektzeiger verwaltet werden, aber auf den Inhalt der Objekte hat es keinerlei Einfluß.
Die TObjectList nimmt dir aber etwas Arbeit ab, da sie selbst die Speicherverwaltung übernimmt und auch gleich die enthaltenen Objekte aufräumen/freigeben kann, wenn man einen Eintrag löscht.

Über eine generische Objektliste (in neueren Delphis, ab D2009) würde man noch die ganzen Typecasts einsparen und somit typsicherer Arbeiten.

PS: Wenn du vom TPicture eh nur die Bitmaps nutzt, dann kannst du auch gleich ein TBitmap verwenden.


Ich hab's mal so grob versucht zusammenzutippen. (der Code rein theoretisch, direkt hier hingeschrieben und demnach ungetestet)
Delphi-Quellcode:
//Init
UndoList := TObjectList.Create(True);
UndoIndex := 0;
BT_Undo.Enabled := False;
BT_Redo.Enabled := False;

//Free
UndoList.Free;

//Save
BT_Undo.Enabled := True;
BT_Redo.Enabled := False;
while UndoList.Count > UndoIndex+1 do
  UndoList.Delete(UndoIndex + 1);
B := TBitmap.Create;
B.Assign(Image1.Picture.Bitmap);
UndoList.Add(B);
Inc(UndoIndex);

//Clear
UndoList.Clear;
UndoIndex := 0;
BT_Undo.Enabled := False;
BT_Redo.Enabled := False;

//Undo
if UndoIndex > 0 then begin
  Dec(UndoIndex);
  Image1.Picture.Bitmap.Assign(TBitmap(UndoList[UndoIndex]));
  BT_Redo.Enabled := True;
  BT_Undo.Enabled := UndoIndex > 0;
end else
  BT_Undo.Enabled := False;

//Redo
if UndoIndex < UndoList.Count-1 then begin
  Inc(UndoIndex);
  Image1.Picture.Bitmap.Assign(TBitmap(UndoList[UndoIndex]));
  BT_Undo.Enabled := True;
  BT_Redo.Enabled := UndoIndex < UndoList.Count-1;
end else
  BT_Redo.Enabled := False;
Und alle Zeichenoperationen natürlich nur auf Image1.Picture.Bitmap .
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 9. Mai 2012 um 02:59 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#8

AW: Undo Redo: Bilder

  Alt 9. Mai 2012, 03:24
Für eine saubere Undo/Redo-Implementierung brauchst du zwei Stacks: einen für die Undo- und einen für die Redo-Operation.
Das sehe ich auch so.
Ausserdem sollte man die ganze Undo/Redo-Logik in eine eigene Klasse (den "Undo/Redo-Manager") auslagern.
Damit wären es dann 3 Objekte.
Nur so bekommt man eine Lösung, die nicht Spaghetticode erinnert.
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#9

AW: Undo Redo: Bilder

  Alt 9. Mai 2012, 05:53
Je nach dem was Du für Manipulationen auf dem "Bild" ausführst, könnte es auch eine Option sein das Bild gar nicht zu verändern sondern es darzustellen und die vorgenommenen Schritte als Information zu verwalten und bei der Darstellung jeweils nacheinander auszuführen.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
R56

Registriert seit: 8. Mai 2012
8 Beiträge
 
#10

AW: Undo Redo: Bilder

  Alt 9. Mai 2012, 08:54
Wenn ich mir himitsu's Quellcode anschaue dürfte das funktionieren, jedoch wird beim ersten mal das Bild vor dem ersten Undo nicht gespeichert...

PS:Hab's grade getestet. Wenn man zwischendurch was neues reinschreibt, wird ein Bild zu oft gespeichert...

PSS: Hab im Forum etwas zu dem Thema gefunden, kann aber igendwie damit wenig anfangen:
http://www.delphipraxis.net/48543-undo-redo-klasse.html

Das erste Problem hab ich mit einer If Abfrage gelöst. Könnte man das 2. Problem lösen, indem man alle darauffolgenden Beiträge löschen tut und das Momentane dann added?

Geändert von R56 ( 9. Mai 2012 um 15:24 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:44 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