Canvas wird gelöscht bzw. "wegraddiert"

Für Fragen von Einsteigern und Programmieranfängern...
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 »

Die Forschleife bringt hier nichts. Daher würde das nicht gehen. Du kannst den Timer z.b. auf 20 oder 40 MS stellen, muss mal schauen.
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 »

Warum bringt die nichts? Würde das nicht bezewecken, dass nur jeder vierte Wert grafisch umgesetzt wird?
Oder darf man im Timer keine For-Schleife benutzen?

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:Warum bringt die nichts? Würde das nicht bezewecken, dass nur jeder vierte Wert grafisch umgesetzt wird?
Oder darf man im Timer keine For-Schleife benutzen?
Relativ betrachtet hast du recht :-) Man kann in TimerEvents sehr wohl FOR-Schleifen benutzen.

Gedacht war bei den Tips, das der Tick (zB. Bewegung) gleich bleibt und nur nach jeder x-ten Berechnung der zeitaufwendigere Zeichenprozeß durchgeführt wird. Dadurch kann der Timer besser seine Teilung halten, die er durch die langsame Grafikroutine verliert.

Bei deiner Version wird die relative Bewegung pro TimerEvent auf das 4. fache gebracht. Der Timer wird genauso unkonstant/zu langsam sein wie original, du hast aber die Möglichkeit jetzt das Intervall auf das 4fache zu strecken, damit gehts natürlich auch.

Zwei Lösungen, was dir besser erscheint nehmen.
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 »

Die Forschleife kann hier nicht in dieser Form gehen. Du müsstest eine Art zeit Schleife einfügen. Nicht per Sleep. Sondern mit einer Localen Integer Variable, z.b. die du mit GettickCount füllst.
Grund:
Innerhalb der Forschleife zeichnest du jetzt ein Bild. Es wird jedoch so schnell gezeichnet, dass du theoretisch nur das letzte siehst. Am einfachsten wäre es, wie schon gesagt, ohne Forschleife mit einem Timer, denn du auf einen bestimmten Interval stellst und Pro onTimer eine Variable hoch zählst.
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 »

@af0815: Ich habe das mit dem Hochzählen ja schon verstanden, ich glaube nur einfach, dass dadurch die Performace nicht viel besser wird, da wir in einem Crashkurs eine grafisch einfach Stoppuhr gemacht haben, und auch da waren die 10 ms langsamer.
@pluto: Ich zeichne doch nicht innerhalb der for-Schleife. Da werden doch nur hintereinander Werte berechnet und der letzte wird dann dem Shape-Objekt zugewiesen.

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:@af0815: Ich habe das mit dem Hochzählen ja schon verstanden, ich glaube nur einfach, dass dadurch die Performace nicht viel besser wird, da wir in einem Crashkurs eine grafisch einfach Stoppuhr gemacht haben, und auch da waren die 10 ms langsamer.
Windows hat einen nicht deterministischen Scheduler. Daher können die Timer abweichen. Du sagst hier dem System bitte rufe mich in 10ms auf, inwieweit das System dem entgegenkommt sei dahingestellt und wird dir auch nicht garantiert. Der Aufruf erfolgt nach 10ms, ev. auch 15ms wenn andere Prozesse mit höheren Prioritäten es verlangt haben. Jeder Prozess bekommt vom Scheduler nach einem bestimmten Verfahren eine Zeitscheibe zugeteilt, so auch die Timer. Brauchen jetzt andere Prozesse mit höherer Priorität Leistung, so wird die auch zugeteilt und die Zeitscheibe der niederen Prozesse verzögert bzw. gekürzt.

Siehe auch in der Wiki (Englisch)
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 »

Vielleicht hilft folgendes Beispiel:
Nehmen wir an, du möchtest eine Animation erstellen. Du hast dir jetzt 4 Grafiken erstellt und das wird jetzt eine Art "Daumkino".

Es gibt natürlich viele Möglichkeiten, dass jetzt Automatisch abspielen zu lassen. Nehmen wir an, du verwendest eine ImageList. Jetzt zeichnest, du alle Grafiken in einer Forschleife auf ein Canvas. Was würde jetzt Passieren ? oder anders gefragt: Würdest du die Animation erkennen können ? Ich meine es jetzt einfach so: Du schreibst in ein OnPaint Event oder beim Klicken auf einen Button das rein. Oder auch in ein Timer. Es geht mir letztendlich nur um die Forschleife. Du könnte ja von 0 bis 3 gehen. Was meinst du ?
MFG
Michael Springwald

martin_frb
Beiträge: 586
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

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

Beitrag von martin_frb »

Also zunächst mal versteh ich die ganzen Antworten: "Die for schleife bringt nix" nicht.

In der Form wie der original Autor sie gemeint hat, bringt die doch genau was sie soll:
- Timer.Interval := 4 * 10; // 40 ms
- in der procedure Timer1Timer:
4 mal berechnen (schnell)
1 mal zeichnen

Davon ausgehend das die Berechnung wirklich nicht zusammengefasst werden kann, ist diese Lösung sogar besser als:
- Timer.Interval := 10; // 10 ms
- in der procedure Timer1Timer:
1 mal berechnen (schnell)
IF (wenn dies ein vierter Aufruf ist) THEN 1 mal zeichnen

Die erste Lösung hat nur ein viertel der Timer-Aufrufe, jeder Aufruf kostet in sich selbst Zeit. Die Timer Message muss vom OS/LCL behandelt werden.

Beide Lösungen leiden unter der Ungenauigkeit des Timer. Sowohl als auch darunter, das der im Timer1Timer ausgeführte Code laenger dauern kann als das Intervall.

Das ließe sich über eine Referenz Zeit verbessern:

procedure BeforeFirstTimerCall;
begin
// object member
TimerLast := TimeInMillSecs(); // 40 ms before
end;

procedure Timer1Timer;
var TimerThis, TimeUsed: ...;
begin
TimerThis := TimeInMillSecs();
TimeUsed := TimeThis - TimeLast;
TimeLast := TimeThis;
for i := 0 to TimeUsed div 10 do begin // fuer jede 10 msec
// calc
end;
// draw
end

------------
Soweit sogut.....

Allerdings, wenn zu viele Ereignisse eintreffen, werden die Paint (paint on real screen) Ereignisse übergangen, bis wieder Zeit ist...... Daher muss man testen ob wirklich gezeichnet wurde. Wenn nicht muss man dafür sorgen das weniger andere Ereignisse anstehen.

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 »

Daher muss man testen ob wirklich gezeichnet wurde
Du meinst, es funken irgendwelche Eventes dazwischen ?
MFG
Michael Springwald

martin_frb
Beiträge: 586
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

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

Beitrag von martin_frb »

pluto hat geschrieben:
Daher muss man testen ob wirklich gezeichnet wurde
Du meinst, es funken irgendwelche Eventes dazwischen ?
Das hängt davon ab wann und wie gezeichnet wird.

Das "painten" auf den aktuellen Handle (also das painten das dann wirklich im Fenster sichtbar wird) sollte normaler weise nur Im OnPaint Ereignis passieren (genau gesagt während der Paint-Message)

Dann würde Timer1Timer auf eine Bitmap zeichnen die dann später übertragen wird?

Das handling der Paint-Message passiert aber nur bei leere msg queue (afaik), Wenn das nächste Timer Ereignis schon in der Queue liegt, wird das vorgezogen.

Um zu vermeiden, das nie gezeichnet wird, kann man im OnPaint ein flag setzten. Ist dieses Flag nicht gesetzt, dann wird im Timer1Timer nicht mehr gezeichnet => der Timer1Timer ist dann schneller fertig, und hoffentlich reicht die Zeit für ein Paint Ereignis.

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 »

martin_frb: Schön, dass du mich verstehst, aber das mit der Referenzzeit habe ich nicht so ganz verstanden.
Also ich habe jetzt die drei Varianten getestet. Dabei habe ich einen Sprung ablaufen lassen, der laut der Anzeige 14,25 s dauert. Nun habe ich jeweils die wahre Zeit gestoppt:
Ohne for-Schleife oder Zähler: 22,5 s.
Mit Zähler: 22 s.
Mit for-Schleife: 17 s.
Die for-Schleife-Lösung scheint also am besten zu funktionieren.

MfG ;)

martin_frb
Beiträge: 586
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

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

Beitrag von martin_frb »

alex189 hat geschrieben:martin_frb: Schön, dass du mich verstehst, aber das mit der Referenzzeit habe ich nicht so ganz verstanden.
Also ich habe jetzt die drei Varianten getestet. Dabei habe ich einen Sprung ablaufen lassen, der laut der Anzeige 14,25 s dauert. Nun habe ich jeweils die wahre Zeit gestoppt:
Ohne for-Schleife oder Zähler: 22,5 s.
Mit Zähler: 22 s.
Mit for-Schleife: 17 s.
Die for-Schleife-Lösung scheint also am besten zu funktionieren.
Denkbar...
Da jedem Timer-Intervall ein par millisecs länger ist als geplant. Mit schleife findet nur ein viertel der Intervalle statt, Die extra zeit ist also geringer.

Über die Referenzzeit: Du gehst davon aus das genau 40 millisecs vergangen sind, es ist aber mehr. Also misst du die Zeit, und berechnest dann entsprechend der tatsächlich abgelaufenen Zeit. (Holst also die versäumte Zeit wieder auf). Damit spielt es keine rolle mehr wie lang das Intervall ist, solange es nur ausreichend Zeit zum Zeichnen lässt.

Übrigens:
for i := o to TimeUsed div 10 do

"div" ist falsch
int(round(TimerUsed / 10, 0))
oder sowas.

damit du auch hin und wieder aufrundest => sonst verlierst du ja doch zeit.

Antworten