In Paint: Resize erkennen und Inhalt von Canvas sichern
-
- Beiträge: 462
- Registriert: Mi 30. Jul 2008, 13:11
- OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
- CPU-Target: 32Bit
- Kontaktdaten:
In Paint: Resize erkennen und Inhalt von Canvas sichern
Hallo!
Problem: Wenn die Komponente vergrößert wird, wird sie für jeden Pixel komplett neu gezeichnet (Paint wird automatisch aufgerufen). Das führt zu Flackern.
Lösungsansatz: Beim Aufruf der Paint-Routine herausbekommen, ob lediglich die Größe geändert wurde und ggf. nur den entstandenen Rand dazuzeichnen.
Restprobleme:
1. Wie bekomme ich heraus, ob der Aufruf durch ein Resizing getriggert wurde? ClientHeight und ClientWidth mit den alten Werten zu vergleichen ist sicherlich möglich, jedoch unter Umständen unsicher...
2. Da das ganze Canvas schon vor dem Aufruf von Paint weiß gezeichnet wurde, muss ich irgendwie nach dem Abarbeiten von Paint den Inhalt meines Canvas sichern, damit ich es beim nächsten Paint-Aufruf wiederherstellen kann (geht ja schneller als komplett neu erstellen, was ja meist nicht nötig ist). Wie mache ich das?
Problem: Wenn die Komponente vergrößert wird, wird sie für jeden Pixel komplett neu gezeichnet (Paint wird automatisch aufgerufen). Das führt zu Flackern.
Lösungsansatz: Beim Aufruf der Paint-Routine herausbekommen, ob lediglich die Größe geändert wurde und ggf. nur den entstandenen Rand dazuzeichnen.
Restprobleme:
1. Wie bekomme ich heraus, ob der Aufruf durch ein Resizing getriggert wurde? ClientHeight und ClientWidth mit den alten Werten zu vergleichen ist sicherlich möglich, jedoch unter Umständen unsicher...
2. Da das ganze Canvas schon vor dem Aufruf von Paint weiß gezeichnet wurde, muss ich irgendwie nach dem Abarbeiten von Paint den Inhalt meines Canvas sichern, damit ich es beim nächsten Paint-Aufruf wiederherstellen kann (geht ja schneller als komplett neu erstellen, was ja meist nicht nötig ist). Wie mache ich das?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- Beiträge: 423
- Registriert: Di 5. Feb 2008, 12:45
- OS, Lazarus, FPC: Linux, Lazarus svn, FPC svn
- CPU-Target: 64Bit
- Kontaktdaten:
Ich weiß nicht so ganz was du ursprünglich verhindern willst...
Nur das flackern?
Kennst du die Option:
Versuche es mal für die Form, vielleicht hilft es ja...
Nur das flackern?
Kennst du die Option:
Code: Alles auswählen
DoubleBuffered:=true
Du magst Freiheit? Gönne es auch deinem Computer mit Linux!
www.alexanderroth.eu
www.alexanderroth.eu
-
- Beiträge: 462
- Registriert: Mi 30. Jul 2008, 13:11
- OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
- CPU-Target: 32Bit
- Kontaktdaten:
DoubleBuffered hilft nicht. Ich will es auch einfach effizient gestalten, die Komponente ist selbstgeschrieben 
Ursprünglich verhindern will ich das Flackern, was dadurch entsteht, dass die Komponente unnötigerweise dauernd komplett neu gezeichnet wird.

Ursprünglich verhindern will ich das Flackern, was dadurch entsteht, dass die Komponente unnötigerweise dauernd komplett neu gezeichnet wird.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- Beiträge: 423
- Registriert: Di 5. Feb 2008, 12:45
- OS, Lazarus, FPC: Linux, Lazarus svn, FPC svn
- CPU-Target: 64Bit
- Kontaktdaten:
hmmm dann kann ich dir leider nicht so viel helfen, aber ich würde mal vermuten, dass es normal ist, und dass du vielleicht einfach neu zeichnen solltest...
Musst du berechnungen anstellen während der berechnung? Dauert es außergewöhnlich lange? Wie zeichnest du?
Hmm also wenn ich das machen würde was du in Punkt 2. beschreibst, dann würde ich erst auf ein TBitmap zeichnen und das dann auf die Canvas kopieren... (weis leider nicht ganz genau wie das geht, geht aber bestimmt, jemand anderes weiß es sicherlich)
Musst du berechnungen anstellen während der berechnung? Dauert es außergewöhnlich lange? Wie zeichnest du?
Hmm also wenn ich das machen würde was du in Punkt 2. beschreibst, dann würde ich erst auf ein TBitmap zeichnen und das dann auf die Canvas kopieren... (weis leider nicht ganz genau wie das geht, geht aber bestimmt, jemand anderes weiß es sicherlich)
Du magst Freiheit? Gönne es auch deinem Computer mit Linux!
www.alexanderroth.eu
www.alexanderroth.eu
-
- Beiträge: 462
- Registriert: Mi 30. Jul 2008, 13:11
- OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
- CPU-Target: 32Bit
- Kontaktdaten:
d.h. man müsste tatsächlich ein verstecktes TCanvas irgendwo auf die Form (z.B. genau unter das eigentliche Steuerelement) legen und darauf kopieren. Einfach ein TCanvas instanzieren und dort hin kopieren geht ja leider nicht (Fehler á la "auf dem Canvas kann nicht gezeichnet werden", braucht wohl ein übergeordnetes Control oder so). Ich hatte gehofft, dass man den Inhalt vielleicht in ein geeignetes array schreiben könnte oder etwas vergleichbar einfaches.
Es handelt sich um eine selbst gezeichnete Listbox, bei der ich darauf geachtet habe nichts unnützes zu zeichnen, z.B. wird beim Scrollen das Bild verschoben statt komplett neu gezeichnet.
Das Flackern tritt vielleicht bei einer ordentlichen Grafikkarte nicht auf (arbeite am Laptop mit Intel Onboard Grafik), aber ich will nicht unnütz so viel Grafikleistung verbraten.
Es handelt sich um eine selbst gezeichnete Listbox, bei der ich darauf geachtet habe nichts unnützes zu zeichnen, z.B. wird beim Scrollen das Bild verschoben statt komplett neu gezeichnet.
Das Flackern tritt vielleicht bei einer ordentlichen Grafikkarte nicht auf (arbeite am Laptop mit Intel Onboard Grafik), aber ich will nicht unnütz so viel Grafikleistung verbraten.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- Beiträge: 423
- Registriert: Di 5. Feb 2008, 12:45
- OS, Lazarus, FPC: Linux, Lazarus svn, FPC svn
- CPU-Target: 64Bit
- Kontaktdaten:
hmmm ich glaube du verstehst mich falsch. Ich meine auf ein TBitmap zeichnen. Und dann mittels eines befehls (in windows ist es bitblt (oder so ähnlich)), wird der Inhalt des Bitmaps direkt in das Canvas übertragen.
hmmm gefällt dir die normale Listbox nicht? Die ist doch super...
hmmm gefällt dir die normale Listbox nicht? Die ist doch super...
Du magst Freiheit? Gönne es auch deinem Computer mit Linux!
www.alexanderroth.eu
www.alexanderroth.eu
-
- 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)
du musst bei deiner Komponente einfach die Methode Resize überladen.
Die wird bei einer Größen Änderung aufgerufen.
Das Flackern liegt daran, das du das was du zeichnen möchtest vorher lieber in ein Buffer Zeichnen solltest. Also in z.b. einer TBItmap du du einmal erstellst und bei Resize setzt und installisiert damit meine ich einmal Fillrect aufrufen.
Bei Paint, kannst du dann einfach alles übermalen mit FillRect und deine restliche Zeichnen Funktion abarbeiten lassen und Fertig.
Die wird bei einer Größen Änderung aufgerufen.
Das Flackern liegt daran, das du das was du zeichnen möchtest vorher lieber in ein Buffer Zeichnen solltest. Also in z.b. einer TBItmap du du einmal erstellst und bei Resize setzt und installisiert damit meine ich einmal Fillrect aufrufen.
Bei Paint, kannst du dann einfach alles übermalen mit FillRect und deine restliche Zeichnen Funktion abarbeiten lassen und Fertig.
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 462
- Registriert: Mi 30. Jul 2008, 13:11
- OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
- CPU-Target: 32Bit
- Kontaktdaten:
Mich hatte an der normalen Listbox das Flackern gestört, und da hab ich mal eine eigene gebaut. Dummerweise hab ich jetzt das Flackern wieder... Aber ich bin um eine Erfahrung reicher und ich weiß wie sie funktioniert. Hab auch einige Sachen vom Ansatz her anders gelöst (z.B. ist Itemindex ein Element selbst, kein Integer). Ich werde jetzt also ein TBitmap zum Sichern des Canvas benutzen und die Resize-Methode überladen. Hoffe dann damit das Problem zu lösen. Leider werde ich wohl dann wegen Urlaub kein Internet mehr haben, um diesen Thread weiter zu verfolgen, ggf. melde ich mich dann in 2 Wochen wieder 

Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- 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)
Warum flackert bei dir die ListBox ?
was verwendest du ? Linux, Windows ? GTK1 GTK2 ? Welche Lazarus Version ?
Das Flackern solltest du melden. Da es sich um Ein Fehler handel könnte. Oder eine Falschen Bedienung...
Hast du mal ein beispiel Projekt ? Wo das Flackern auftritt ? und wann Flackert es ?
Beim Klicken, beim Scrollen, ?
was verwendest du ? Linux, Windows ? GTK1 GTK2 ? Welche Lazarus Version ?
Das Flackern solltest du melden. Da es sich um Ein Fehler handel könnte. Oder eine Falschen Bedienung...
Hast du mal ein beispiel Projekt ? Wo das Flackern auftritt ? und wann Flackert es ?
Beim Klicken, beim Scrollen, ?
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 462
- Registriert: Mi 30. Jul 2008, 13:11
- OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
- CPU-Target: 32Bit
- Kontaktdaten:
Es Flackert beim Vergrößern der Listbox, dabei wird für jeden einzelnen Pixel Paint aufgerufen. Wenn die Liste eine große Fläche hat, flackert es demnach auch schlimmer. Das Problem tritt wohl nur bei solch schwachen Grafikkarten wie meiner auf. Als Bug würde ich das nicht bezeichnen wollen. Außerdem handelt es sich jetzt aktuell um mein eigenes Produkt...
Die Resize-Prozedur hilft mir übrigens nicht weiter, oder ich erkenne die Stelle nicht. Kann man innerhalb von Paint herausbekommen, ob der Aufruf von einem Resize getriggert worden ist (notfalls könnte ich mir den Hinweis in der Resize selbst setzen)?
Die Resize-Prozedur hilft mir übrigens nicht weiter, oder ich erkenne die Stelle nicht. Kann man innerhalb von Paint herausbekommen, ob der Aufruf von einem Resize getriggert worden ist (notfalls könnte ich mir den Hinweis in der Resize selbst setzen)?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- 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: In Paint: Resize erkennen und Inhalt von Canvas sichern
Hallo RSE,
Damit würdest du gleich 2 Fliegen mit einer Klappe schlagen: Das Flackern würde ev. weniger UND die von Paint gezeichnete Zeichnung wäre gesichert.
Das Flackern kannst du ganz beseitigen, indem du mit Timern arbeitest - und nach onresize z.B. eine halbe Sekunde Pause einprogrammierst, bevor er erneut zeichnet.
Gruß, Euklid
Wie wärs, wenn du Paint in einem Bitmap im Arbeitsspeicher zeichnen lässt, und dieses dann auf die Canvas kopierst?RSE hat geschrieben: 2. Da das ganze Canvas schon vor dem Aufruf von Paint weiß gezeichnet wurde, muss ich irgendwie nach dem Abarbeiten von Paint den Inhalt meines Canvas sichern, damit ich es beim nächsten Paint-Aufruf wiederherstellen kann (geht ja schneller als komplett neu erstellen, was ja meist nicht nötig ist). Wie mache ich das?
Damit würdest du gleich 2 Fliegen mit einer Klappe schlagen: Das Flackern würde ev. weniger UND die von Paint gezeichnete Zeichnung wäre gesichert.
Code: Alles auswählen
//...
var SpeicherBitmap: TBitmap;
begin
//... wenn z.B. das Bild auf Form1.Image1 ausgegeben werden sol:
SpeicherBitmap.Width:=Form1.Image1.Width;
SpeicherBitmap.Height:=Form1.Image1.Height;
// Hier wird nun auf die SpeicherBitmap gezeichnet anstatt auf Form1.Image1
Form1.image1.canvas.Draw(0,0,SpeicherBitmap); //SpeicherBitmap wird schließlich auf Image1 gezeichnet.
//...
end;
Gruß, Euklid
-
- Beiträge: 462
- Registriert: Mi 30. Jul 2008, 13:11
- OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
- CPU-Target: 32Bit
- Kontaktdaten:
Ich habe jetzt Zeit gefunden das umzusetzen. In Resize setze ich eine eigene Variable Resizing auf true. In Paint habe ich folgenden Quelltext (Canvas ist von meiner Listbox, Bitmap ist die Sicherungskopie):
Leider scheint der Kopiervorgang nicht schneller zu sein als ZeichneKomplettNeu, da das Flimmern genauso weiterhin vorhanden ist. Es besteht kein Unterschied zwischen einer Verkleinerung und einer Vergrößerung der Listbox.
Kann man das Ganze noch wesentlich beschleunigen (außer das Kopieren ins Bitmap wegzulassen wenns unnötig ist), oder befinde ich mich in einer Sackgasse?
Code: Alles auswählen
if Resizing and (ClientWidth <= Bitmap.Width) and
(ClientHeight <= Bitmap.Height) then begin
Canvas.CopyRect(classes.rect(0,0,ClientWidth,ClientHeight),
Bitmap.Canvas,classes.rect(0,0,ClientWidth,ClientHeight));
end else begin
ZeichneKomplettNeu;
end;
Resizing := false;
Bitmap.Width := ClientWidth;
Bitmap.Height := ClientHeight;
Bitmap.Canvas.CopyRect(classes.rect(0,0,ClientWidth,ClientHeight),
Canvas,classes.rect(0,0,ClientWidth,ClientHeight));
Kann man das Ganze noch wesentlich beschleunigen (außer das Kopieren ins Bitmap wegzulassen wenns unnötig ist), oder befinde ich mich in einer Sackgasse?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!
-
- 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)
Also die Schritte um das Flimmern zu vermeiden beim Zeichen währe folgende:
01 - einen Buffer von Typ TBitmap anlegen/Installisieren aber nur einmal !
02 - Die Größe setzten und einmal mit FillRect alles übermalen
03 - Eine Paint Mehtode erstellen und rein Zeichnen, vorher alles löschen mit FillRect.
04 - Wenn alles gezeichnet ist könntest du mit bitblt arbeiten oder du sagst z.b. Canvas.Draw(0,0, Buffer)
Wenn du diese Schritte beim zeichnen befolgst dürfte es eigentlich nicht mehr Flimmern.
Es ist Wichtig in den Buffer rein zu zeichnen. und CopyRect nehme ich schon lange nicht mehr da er unter Lazarus auch ein Fehler haben soll, welchen Genau weiß ich nicht mehr und ob dieser Fehler immer noch da ist weiß ich auch nicht !
01 - einen Buffer von Typ TBitmap anlegen/Installisieren aber nur einmal !
02 - Die Größe setzten und einmal mit FillRect alles übermalen
03 - Eine Paint Mehtode erstellen und rein Zeichnen, vorher alles löschen mit FillRect.
04 - Wenn alles gezeichnet ist könntest du mit bitblt arbeiten oder du sagst z.b. Canvas.Draw(0,0, Buffer)
Wenn du diese Schritte beim zeichnen befolgst dürfte es eigentlich nicht mehr Flimmern.
Es ist Wichtig in den Buffer rein zu zeichnen. und CopyRect nehme ich schon lange nicht mehr da er unter Lazarus auch ein Fehler haben soll, welchen Genau weiß ich nicht mehr und ob dieser Fehler immer noch da ist weiß ich auch nicht !
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 462
- Registriert: Mi 30. Jul 2008, 13:11
- OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
- CPU-Target: 32Bit
- Kontaktdaten:
@01: Was meinst du genau mit nur einmal initialisieren? Alle Zeilen zeichnen und dann immer nur den entsprechenden Ausschnitt darstellen funktioniert nicht.
1. Die Liste kann sehr lang werden, dann werden Unmengen von Speicherplatz verbraten
2. Wenn die Breite geändert wird, muss sowieso komplett neu gezeichnet werden, auch beim Verkleinern, weil auch rechtsbündig Text dargestellt wird.
@02: Mit FillRect alles übermalen kann ich mir schenken:
1. Das passiert sowieso, sonst müsste ich es nicht erst wiederherstellen. Ich weiß aber nicht, wo ich das abstellen kann (meine Listbox ist von TPanel abgeleitet).
2. Ich übermale ja dann mit Draw sowieso nochmal alles, weil mein Buffer ist immer mindestens geauso groß wie die Zeichenfläche in der Listbox
@04: BitBlt kenne ich gar nicht, es scheint aber windows-spezifisch zu sein. Ich möchte lieber bei plattformunabhängigen Funktionen bleiben. Falls sie in Lazarus plattformunabhängig implementiert ist, wie benutze ich sie (Beispiel-Link)?
1. Die Liste kann sehr lang werden, dann werden Unmengen von Speicherplatz verbraten
2. Wenn die Breite geändert wird, muss sowieso komplett neu gezeichnet werden, auch beim Verkleinern, weil auch rechtsbündig Text dargestellt wird.
@02: Mit FillRect alles übermalen kann ich mir schenken:
1. Das passiert sowieso, sonst müsste ich es nicht erst wiederherstellen. Ich weiß aber nicht, wo ich das abstellen kann (meine Listbox ist von TPanel abgeleitet).
2. Ich übermale ja dann mit Draw sowieso nochmal alles, weil mein Buffer ist immer mindestens geauso groß wie die Zeichenfläche in der Listbox
@04: BitBlt kenne ich gar nicht, es scheint aber windows-spezifisch zu sein. Ich möchte lieber bei plattformunabhängigen Funktionen bleiben. Falls sie in Lazarus plattformunabhängig implementiert ist, wie benutze ich sie (Beispiel-Link)?
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!