Canvas wird gelöscht bzw. "wegraddiert"

Für Fragen von Einsteigern und Programmieranfängern...
alex189
Beiträge: 36
Registriert: Di 13. Apr 2010, 19:15
OS, Lazarus, FPC: Windows 7 Ultimate 64bit (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: 32Bit-Anw.
Wohnort: Nürnberg

Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von alex189 »

Hallo liebes Lazarusforum!

Ich bin in der 11. Klasse an einem Gymnasium und meine Seminararbeit wird eine Simulation der Physik des Skispringens.
Der Benutzer dieses Programms sieht also einen Skisprung (in 2D) von der Seite und kann die entsprechenden physikalischen Werte ändern und deren Auswirkungen sehen.
Der Skispringer wird dabei durch ein Shape-Objekt (später vllt durch ein kleines Bild) dargestellt. Mithilfe eines Timer-Objekts werden in jedem Timer-Durchlauf die neuen Koordinaten und Geschwindigkeiten berechnet und dem Shape-Objekt zugewiesen.
Den Hang lasse ich zuvor folgendermaßen auf das Canvas einer paintbox zeichnen:
Zur Verdeutlichung hier die Prozedur, mit der der Hang gezeichnet wird:

Code: Alles auswählen

//xzeich und yzeich sind die Koordinaten des aktuellen Punktes.
//xzeich wird immer erhöht und yzeich je nachdem, an welcher Stelle, mithilfe von Funktionen berechnet.
procedure TForm1.Button3Click(Sender: TObject);
begin
  while xzeich<280 do begin
  xzeichalt:=xzeich;
  xzeich:=xzeich+1;
  yzeichalt:=yzeich;
  if xzeich<=35 then
  yzeich:=0.65*xzeich+5
  else if xzeich<=80 then
  yzeich:=sqrt(90*90-(xzeich-84.04895155)*(xzeich-84.04895155))-52.70992546+5
  else if xzeich<=227.1 then
  yzeich:=-(0.000052*(xzeich-80)*(xzeich-80)*(xzeich-80)-0.01148*(xzeich-80)*(xzeich-80))+40+5
  else
  yzeich:=122.892421+5;
  //Hier werden die Werte auf das Canvas gezeichnet:
  paintbox1.canvas.moveto(round(faktor*xzeichalt),round(faktor*yzeichalt));
  paintbox1.canvas.lineto(round(faktor*xzeich),round(faktor*yzeich));
  end;
  button1.enabled:=true;
end;
Und damit komme ich zu meinem Problem:
Wenn ich das Formularfenster minimiere, bzw. ein anderes Fenster über den Hang rutscht, verschwindet dieser, also das auf das Canvas Gezeichnete. Auch wenn das Shape-Objekt den Hang streift, wird dieser Teil sozusagen wegraddiert.

Wie kann ich dieses Phänomen abschaffen?

Falls ihr euch eine Vorabversion der Simulation anschauen wollt, könnt ihr sie hier runterladen (Die Ausgabe von vx und vy in den Labels ist manchmal fehlerhaft, wird noch behoben).

Danke schonmal. :wink:
MfG
alex189

PS: Falls ihr sonstige Fragen zu diesem Projekt habt, könnt ihr sie natürlich gerne stellen.

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von Euklid »

Hallo Alex,

verwende anstatt eine PainBox eine TImage. Darauf kannst Du zeichnen, wie Du es bereits bei der Paintbox machst, nur dass sie den Inhalt speichert.
Die Image findest Du im Reiter "Additional" des Objektleiste.

Viele Grüße, Euklid

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

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von theo »

Mit PaintBox etc. sollte man immer im OnPaint Ereignis auf den Canvas zeichnen.

alex189
Beiträge: 36
Registriert: Di 13. Apr 2010, 19:15
OS, Lazarus, FPC: Windows 7 Ultimate 64bit (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: 32Bit-Anw.
Wohnort: Nürnberg

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von alex189 »

Ich hab jetzt beides ausprobiert.
@theo: Hab die Prozedur nun in das OnPaint-Ereignis der Paintbox (oder ist des Forms besser?) geschrieben und jetzt funktioniert es wunderbar.
@Euklid: Ich habe ein TImage an die Stelle der TPaintbox gesetzt und in der Zeichenprozedur paintbox durch image ersetzt. Wenn ich dann aber auf den Button zum Zeichnen klicke, wird das Image einfach schwarz.

Also es geht jetzt eigentlich, aber jetzt würde ich schon gerne wissen, warum das mit TImage nicht richtig klappt.

Und nebenbei (oder neuer Thread besser?): Kann man die Performance des Timers irgendwie verbessern? Denn die Zeit vergeht in meiner Simulation so langsam. :)

mfg ;)

Eb
Lazarusforum e. V.
Beiträge: 240
Registriert: Di 5. Feb 2008, 15:32
OS, Lazarus, FPC: Linux Mint - Laz 2.2.0
CPU-Target: 64Bit
Wohnort: Stuttgart

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von Eb »

Das Intervall in welchem das Timer-Event ausgelöst wird, steuerst du über die Eigenschaft 'Interval' des Timers - das ist die Zeit in Millisekunden.

alex189
Beiträge: 36
Registriert: Di 13. Apr 2010, 19:15
OS, Lazarus, FPC: Windows 7 Ultimate 64bit (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: 32Bit-Anw.
Wohnort: Nürnberg

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von alex189 »

Ja, das weiß ich schon. Habs auf 10ms gestellt, aber er läuft merklich langsamer.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von pluto »

Eine andere Möglichkeit wäre noch, du nutzt eine PaintBox und Zeichnest in einem Buffer und bei OnPaint kopierst du einfach nur noch den Inhalt vom Buffer in das Canvas.
MFG
Michael Springwald

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von Euklid »

Alex: Du möchtest etwas animieren und für eine flüssige Bildfolge brauchst Du einen schnelleren Timer?
Wenn Du direkt auf die Canvas zeichnest, könnte die Geschwindigkeit abgebremst werden, da mit jedem Zeichenschritt (LineTo bspw.) die Grafikkarte angesprochen werden muss. Hier gäbe es also schnellere Alternativen...

Viele Grüße, Euklid

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von pluto »

Für einfache Animationen reicht auch Canvas vollkommen aus. Wenn du nicht zu viel möchtest.
MFG
Michael Springwald

alex189
Beiträge: 36
Registriert: Di 13. Apr 2010, 19:15
OS, Lazarus, FPC: Windows 7 Ultimate 64bit (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: 32Bit-Anw.
Wohnort: Nürnberg

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von alex189 »

Naja, ich möchte das Programm natürlich so gut machen, wie ich kann.
Also, beim Zeichen des Hangs (dabei zeichne ich ja nur auf das Canvas) gibt es ja jetzt eigentlich keine Probleme.
Das Problem liegt darin, dass beim Skisprung dann die Zeit langsamer vergeht, als normal, weil der Timer das 10ms-Intervall anscheinend nicht schafft. Und dabei zeichne ich ja nicht auf das Canvas, sondern bewege nur das Shape-Objekt in jedem Durchgang an eine neue Position (oder wird der Hang auch jedesmal neu gezeichnet, wegen dem OnPaint? Aber so verzögert war es auch schon ohne OnPaint). Das Timer-Intervall muss deswegen so klein sein, weil ich die Werte mit der Kleinschrittmethode berechne, und je größer da die Schritte sind, desto fehlerhafter die Ergebnisse.

MfG ;)

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6771
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von af0815 »

alex189 hat geschrieben: Das Timer-Intervall muss deswegen so klein sein, weil ich die Werte mit der Kleinschrittmethode berechne, und je größer da die Schritte sind, desto fehlerhafter die Ergebnisse.
Provokante Frage: Musst du jedesmal zeichnen ?!
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

alex189
Beiträge: 36
Registriert: Di 13. Apr 2010, 19:15
OS, Lazarus, FPC: Windows 7 Ultimate 64bit (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: 32Bit-Anw.
Wohnort: Nürnberg

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von alex189 »

Du meinst, dass ich z.B. ne kleine for-Schleife im Timer hab, sodass z.B. nur jedes vierte Ergebnis dem Shape-Objekt zugewiesen wird?
Das habe ich mir auch schonmal gedacht, wäre auf jeden Fall einen Versuch Wert, falls ich das richtig verstanden habe.

MfG

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6771
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von af0815 »

alex189 hat geschrieben:Du meinst, dass ich z.B. ne kleine for-Schleife im Timer hab, sodass z.B. nur jedes vierte Ergebnis dem Shape-Objekt zugewiesen wird?
Das habe ich mir auch schonmal gedacht, wäre auf jeden Fall einen Versuch Wert, falls ich das richtig verstanden habe.

MfG
Keine "FOR-Schleife", sondern ganz einfach einen Zähler den du bei jedem Einsprung in den Timer hochzählst - Achtung der muß global definiert sein, nicht innerhalb des Timereinsprungs. Wenn der Zähler zB. 10 (10x10ms = 100ms) erreicht, so zeichnest du.

PS. das Auge ist träge, sonst würde das alte Röhren TV nicht funktionieren, somit brauchst du nicht immer Zeichen und das ganze geht flotter.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von pluto »

Du kannst im Timer einfach in einem Bestimmten Interval einen Zähler hochzählen. Denn müsstest du vorher mit einem Wert z.b. 0 belegen.
MFG
Michael Springwald

alex189
Beiträge: 36
Registriert: Di 13. Apr 2010, 19:15
OS, Lazarus, FPC: Windows 7 Ultimate 64bit (L 0.9.28.2 Beta FPC 2.2.4)
CPU-Target: 32Bit-Anw.
Wohnort: Nürnberg

Re: Canvas wird gelöscht bzw. "wegraddiert"

Beitrag von alex189 »

So wäre das natürlich auch eine Möglichkeit, aber da müsste ich den Timer auf 10 ms lassen und ich glaube ja, dass er einfach dieses kleine Intervall nicht schafft, auch ohne Zeichnen.
Ich meinte das so in etwa:

Code: Alles auswählen

procedure TForm1.Timer1Timer(Sender: TObject);
var i: Integer;
begin
for i:=1 to 4 do
begin
//4 mal Berechnen der neuen Werte
end
//Zuweisung des letzten Wertes an das Shape-Objekt
end
Und dann würde ich das Intervall z.B. auf 40ms stellen.
Würde doch auch gehen, oder?

greez ;)

Antworten