Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Label in Schleife zeichnen lassen (https://www.delphipraxis.net/210241-label-schleife-zeichnen-lassen.html)

Gruber_Hans_12345 23. Mär 2022 07:59

Label in Schleife zeichnen lassen
 
Eine kurze frage:

Ich habe eine Schleife die von 1 bis 1.000.000 zählt.
Nun möchte ich möglichst schnell in der Schleife ein Label aktualisieren - deswegen habe ich KEIN Application.Processmessages drinnen (dauert zu lange)

wollte es einfach mit:
Delphi-Quellcode:
Label1.Caption := IntToStr(i);
TCrackedLabel(Label1).Paint;
Das Label ist nicht transparent.
Problem ist, das es flackert bzw teilweise nur der clBtnFace hintergrund zu sehen ist, also der Text gar nicht.

Wie wenn im Hintergrund wer noch mal drüber zeichnet, oder wie wenn der Text erst verzögert gezeichnet werden würde.

Habe selbiges auch mal getestet das ich den Text selber auf den Canvas zeichne, das hat auch nicht funktioniert.

Wer könnte mir da noch dazwischenfunken?

jaenicke 23. Mär 2022 08:10

AW: Label in Schleife zeichnen lassen
 
Das Problem ist, dass es nicht anders geht, als auch den Hintergrund neu zu zeichnen. Denn der neue Text deckt ja nicht unbedingt den alten komplett ab. Normalerweise kann man Flackern vermindern, indem man das Neuzeichnen zeitweise unterbindet. Bei so schnellen Aktualisierungen hilft das aber auch nicht.

Ein TStaticText sollte weniger flackern.

Sinnvoller ist aber eine bessere Lösung:
So schnell kann das doch ohnehin niemand wahrnehmen. Sinnvoller ist daher, dass du die Aktualisierungen nicht bei jedem Durchlauf machst, sondern nur z.B. alle x Durchläufe oder alle x Millisekunden. Das reduziert effektiv das Flackern und verringert zudem den Aufwand für das Neuzeichnen, weshalb der Ablauf selbst beschleunigt wird.

Gruber_Hans_12345 23. Mär 2022 08:14

AW: Label in Schleife zeichnen lassen
 
Ja das wäre mir schon klar, deswegen habe ich das Label auf Transparent := FALSE gesetzt, dadurch zeichnet das Label ja voher den Hintergrund auf clBtnFace.

Zweitens ich habe es schon das ich nur alle 20ms mal zeichne.

Aber trotzdem passiert es bei mir dann, das ich teilweise dann für ne sekunde oder so nur den hintergrund sehe also alles clBtnFace ist, und KEIN text, öfters blinkt dann der Text mal auf.
Wie wenn der Text nicht gleich gezeichnet wird

Werde aber auf jeden Fall auf static Text umstellen

Gruber_Hans_12345 23. Mär 2022 08:16

AW: Label in Schleife zeichnen lassen
 
Was mir auch komisch vorkommt.
Wenn ich es mit dem Debuger durchgehe, und nebenbei das Fenster sehe.

Dann sehe ich das wenn er den FillRect macht, ist der Text im Fenster weg (logisch)
Aber nach dem DrawText, sieht man im Fenster noch nix.
Erst wenn er das nächste mal wieder zum FillRect kommt im Debugger, dann sehe ich im Fenster das nun der alte Text da steht.

hoika 23. Mär 2022 09:41

AW: Label in Schleife zeichnen lassen
 
Hallo,
1 bis 1.000.000 zählt.

Willst Du jetzt 1.000.000 neu zeichnen.
Macht für mich keinen Sinn.

Besser z.B. in bestimmten Zeitpunkten (hier alle 1000)

Delphi-Quellcode:
if (i mod 1000)=0 then
begin
  Label.Caption:= 'bla';
  Application.ProcessMessages;
end;

Gruber_Hans_12345 23. Mär 2022 09:45

AW: Label in Schleife zeichnen lassen
 
nein, ich zeichne nur alle 20ms sowas
Delphi-Quellcode:
if (fLastRepaint = 0) or (fRepaintEvery = 0) or (GetTickCount > fLastRepaint+fRepaintEvery) then begin
  fLastRepaint           := GetTickCount;
  Label1.Paint;
end;
aber ich will eben keine ProcessMessages, sondenr nur das .paint

jaenicke 23. Mär 2022 10:19

AW: Label in Schleife zeichnen lassen
 
Vielleicht wäre es sinnvoller mit einem Thread und einer threadbasierten Anzeige zu arbeiten. Ich habe hier vor einiger Zeit ein paar multithreadfähige Komponenten angefangen:
https://github.com/jaenicke/MTCL
Damit kannst du ein zweites Fenster aufmachen und direkt aus einem Thread heraus ohne Synchronisierung aktualisieren. Dann brauchst du auch kein ProcessMessages.

Es gab dafür offenbar kein Interesse, deshalb habe ich da nicht viel weiter gemacht, aber grundlegende Funktionen (Textanzeige, Fortschjrittsanzeige, Positionierung, Schriftarten) sind vorhanden, siehe Demo.

Mein nächstes Ziel ist z.B. die Implementierung von Anchors.

jziersch 25. Mär 2022 08:35

AW: Label in Schleife zeichnen lassen
 
Zitat:

Zitat von Gruber_Hans_12345 (Beitrag 1503821)
nein, ich zeichne nur alle 20ms sowas ... aber ich will eben keine ProcessMessages, sondenr nur das .paint

Willst Du eine Statusausgabe für den Progress in einem Thread?

Ich empfehle die Verwendung einer gelockten globalen variable/record. Im einfachsten Fall verwende einfach
TInterlocked.Increment(FMyProgress);
TInterlocked.Increment(FMyProgressHasChanged);

Du kannst in deiner UI einen Timer nehmen und dort alle X ms abfragen ob sich FMyProgressHasChanged geändert hat, und wenn ja dein Label/UI mit den Daten aus FMyProgress zu aktualisieren.

Schau Dir mal die Klasse TMultiReadExclusiveWriteSynchronizer an. Damit kann man sehr effektive Locks realisieren. Das Prinzip ist immer, dass ein Thread nur auf seinen Daten arbeitet und einen gelockten 2. Datensatz dafür verwendet, bei Bedarf Daten dem Hautpformular zur Verfügung zu stellen.

Ich empfehle einen riesen Bogen um TThread.Synchronize zu machen. Das Ding hätte nie erfunden werden sollen.

Falls es nicht um threads geht schau mal hier: https://www.delphipraxis.net/1503595-post7.html
Vielleicht reicht auch schon ein Label1.Update.

Gruber_Hans_12345 25. Mär 2022 11:11

AW: Label in Schleife zeichnen lassen
 
Ja will das ganze ohne Thread.

und ja das TLAbel.Update sieht zumindest auf den ersten Blick mal genau nahc dem aus was ich brauche :D Danke

Gruber_Hans_12345 25. Mär 2022 11:13

AW: Label in Schleife zeichnen lassen
 
Das mit dem Thread klingt zwar auch sehr interessant, werde mir das bei Gelegenheit auch mal anschauen, sowas könnte ich für den Fortschritt bei sql Abfragen vorstellen.
Vorallem, wenn das .Open mal länger dauert, das man nicht glaubt alles ist gerade tot (das sql.Open MUSS teils im Hauptthread passieren - daher Progress oder "ich bin nicht tot" anzeige dann ausgelagert)

Aber für den aktuellen Fall zu oversized


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:57 Uhr.
Seite 1 von 2  1 2      

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