Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Flakern trotz DoubleBuffer? (https://www.delphipraxis.net/71934-flakern-trotz-doublebuffer.html)

xZise 22. Jun 2006 16:46


Flakern trotz DoubleBuffer?
 
Bei mit Flackert eine ProgressBar und ein TLabel, trotz
Delphi-Quellcode:
DoubleBuffered := true
! Habe ich da einen Fehler gemacht?

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  i, j, Start, l : Integer;
  k : Extended;
  p: ^PixArray;
begin
  Start := GetTickCount;

  PBProgress.Max := Image.Height * Image.Width * 3;
  PBProgress.Position := 0;

  k := 255 / (TBColors.Position - 1);

  for i := 0 to Image.Height - 1 do begin

    p := Image.Picture.Bitmap.ScanLine[i];

    for j := 0 to Image.Width do begin

      for l := 1 to 3 do begin
        p^[l] := Round(Round(p^[l] / k) * k);

        PBProgress.Position := PBProgress.Position + 1;
        PBProgress.Refresh;
      end;


      LTime.Caption := 'Working (' + IntToStr((GetTickCount - Start) div 1000) + ' s)';
      LTime.Refresh;

      inc(p);
    end;
    if CBRefresh.Checked then
      Image.Repaint;
  end;

  LTime.Caption := 'Ready (' + FloatToStr((GetTickCount - Start) / 1000) + ' s)';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DoubleBuffered := true;
end;

SirThornberry 22. Jun 2006 16:53

Re: Flakern trotz DoubleBuffer?
 
Verwende anstelle von Repaint lieber invalidate. Dadurch hat bei mir das flackern aufgehört.

xZise 22. Jun 2006 16:57

Re: Flakern trotz DoubleBuffer?
 
Danke! Manchmal zuckt er noch, aber ansonsten funktioniert es auf jeden falle besser. Allerdings funktioniert es nicht bei Image.invalidate!

Der_Unwissende 22. Jun 2006 17:03

Re: Flakern trotz DoubleBuffer?
 
Hi,
es gibt mindest. zwei Dinge.
Das erste ist, DoubleBuffered muss für das direkte Elterncontrol gesetzt werden, liegt also dein ProgressBar auf einem Control (z.B. einem Panel), muss für dieses getrennt das DoubleBuffered gesetzt werden.
Ansonsten kann es sein, dass du dein ProgressBar an sich viel zu häufig neu zeichnest. Eine Zuweisung des Fortschritts führt hier immer zum Neuzeichnen. Es ist einfacher, wenn du ein wenig die ALU mit dem Dreisatz bemühst und 'nur' Werte zwischen 0 und 100 zuweist. Wenn du hier ausrechnest, wieviel Prozent du vom gesamten Fortschritt hast und nur den Wert zuweist, wenn sich auch was geändert hat, dann wird deutlich seltener neu gezeichnet und es bleibt eine Menge mehr Rechenzeit für den Rest.

Gruß Der Unwissende

xZise 22. Jun 2006 17:10

Re: Flakern trotz DoubleBuffer?
 
Zitat:

Zitat von Der_Unwissende
Das erste ist, DoubleBuffered muss für das direkte Elterncontrol gesetzt werden, liegt also dein ProgressBar auf einem Control (z.B. einem Panel), muss für dieses getrennt das DoubleBuffered gesetzt werden.

Ist direkt auf der Form!

Zitat:

Zitat von Der_Unwissende
Ansonsten kann es sein, dass du dein ProgressBar an sich viel zu häufig neu zeichnest. Eine Zuweisung des Fortschritts führt hier immer zum Neuzeichnen. Es ist einfacher, wenn du ein wenig die ALU mit dem Dreisatz bemühst und 'nur' Werte zwischen 0 und 100 zuweist. Wenn du hier ausrechnest, wieviel Prozent du vom gesamten Fortschritt hast und nur den Wert zuweist, wenn sich auch was geändert hat, dann wird deutlich seltener neu gezeichnet und es bleibt eine Menge mehr Rechenzeit für den Rest.

Hast du recht, aber so war es einfacher xP Mal sehen ^^

Das mit der Zeitanzeige (sind ja nur Sekunden) dachte ich auch vielleicht zu verbessern, wenns eine ist:
Delphi-Quellcode:
if {Wert den man hat} <> LTime.caption then
  LTime.caption := {Wert}
Ist das leistungssteigerend? Weil da ist dann ja immerhin eine If-abfrage hinzugekommen!

SirThornberry 22. Jun 2006 17:29

Re: Flakern trotz DoubleBuffer?
 
die If-Abfrage ist bedeutend schneller als wenn immer weider neu gemalt werden muss. Denn beim malen werden in Paintroutinen auch Abfragen duchgeführt bzw. ist da ja schon die Case-Anweisung um die Message für's neumalen auzuwerten.

Der_Unwissende 22. Jun 2006 17:32

Re: Flakern trotz DoubleBuffer?
 
Nun ja, eine If-Abfrage ist so ziemlich nichts an Rechenzeit (da gibt es sogar Vorhersagemechanismen für). Das Neuzeichnen hingegen ist eine ganze Kette von Operationen, einfach mal viel viel viel mehr als eine If-Abfrage. Du kannst einfach gesagt ein weiteres If gegen jedes neuzeichnen völlig vernachlässigen.
Wie gesagt, es gilt auch (insbesondere) für deine Progressbar, nicht nur für die angezeigte Zeit. Die kannst du natürlich noch in einer Variable zwischenspeichern ((GetTickCount - Start) div 1000), da du hier weder einen String verwendest, noch die Umwandlung Integer->String, hast du schon die Rechenzeit raus, die eine If-Abfrage benötigt (wie gesagt, dass Neuzeichnen kommt noch extra hinzu).

xZise 22. Jun 2006 17:34

Re: Flakern trotz DoubleBuffer?
 
Ah danke!

Eine Frage:
Wenn ich 300 Elemente habe (3x if (10,10,3)), wie passe ich dann die Bar an, dass er alle 3 einen "vorgeht"?
Bisher habe ich das damit gelöst:
Delphi-Quellcode:
Round(100 * ((i * j * l) / (Image.Height * Image.Width * 3)))
Zur Info:
- i,j und l sind Schleifenvariablen
- Image.Height, Image.width und die 3 (xP) sind die Schleifenmaximen!

Aber das scheints nicht zu tun ^^


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz