![]() |
Flimmern bei bewegten Bitmaps für eine Prozessvisualisierung
Hallo,
ich möchte für die grafische Darstellung (Prozessvisualisierung) einer industriellen Automation eine Bitmap auf der Canvas einer Form hin- und herbewegen. Dazu frage ich die EW bzw. MW einer Siemens S5 in einem bestimmten Takt über RS232 und mit einem "Timer.Interval := 1" ab, liegt also im Millisekunden-Bereich, je nach Rechnerpower und Konsistenz der SPS. Die Y-Position der Bitmap ist konstant, jedoch ändert sich ständig der X-Wert. Diesen liefert mir die SPS. Nach einer Positionsänderung der Bitmap lasse ich die Canvas über die Methode Paint des Formulars neu zeichnen, und zwar in einem begrenzten Bereich. Hierbei kommt es unweigerlich zum Flimmern der Animation. Hat jemand vielleicht eine Idee, wie ich das abstellen kann ? Hier der Code:
Delphi-Quellcode:
Und noch zwei Screenshots:
procedure TForm1.FormPaint(Sender: TObject);
var x: integer; begin x:= xOffset + xMove; Canvas.PolyLine( [Point(10, 10), Point(720, 10), Point(720, 350), Point(10, 350), Point(10, 10)]); Canvas.FillRect(Rect(11, 11, 719, 349)); Canvas.Draw(x, yOffset, Bmp); end; procedure TForm1.Button1Click(Sender: TObject); begin Bmp.LoadFromFile('Grafik2.bmp'); Timer1.Enabled:= true; end; procedure TForm1.Button2Click(Sender: TObject); begin Bmp.LoadFromFile('Grafik.bmp'); Timer1.Enabled:= false; Timer2.Enabled:= false; Paint; end; procedure TForm1.Timer1Timer(Sender: TObject); begin xMove:= xMove + 10; if xMove >= 500 then begin Bmp.LoadFromFile('Grafik3.bmp'); Timer1.Enabled:= false; Timer2.Enabled:= true; end; Paint; end; procedure TForm1.Timer2Timer(Sender: TObject); begin xMove:= xMove - 10; if xMove <= 0 then begin Bmp.LoadFromFile('Grafik2.bmp'); Timer2.Enabled:= false; Timer1.Enabled:= true; end; Paint; end; procedure TForm1.TrackBar1Change(Sender: TObject); begin Timer1.Interval:= TrackBar1.Position; Timer2.Interval:= TrackBar1.Position; Edit1.Text:= IntToStr(TrackBar1.Position); end; ![]() ![]() Danke für eure Vorschläge. Gruß, Andreas |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
Hallo!
Setze die DoubleBuffered Eigenschaft der Form auf True. |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
Hallo Andreas,
Hast du schon die Eigenschaft DoubleBuffered vom Formular auf true gesetzt? Das sollte das flimmern unterdrücken. grüße, daniel |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
Hi toms, hi Sanchez,
der Tipp mit dem DoubleBuffered := true bewirkt leider nichts. Ich zeichne die Bitmap direkt auf die Canvas der Form. Soweit ich weiß, hat DoubleBuffered nur einen positiven Nutzen bei Nachfahren von TWinControl. TForm gehört zwar dazu, aber es bewirkt nichts. Könnte es sein, dass die Methode Canvas.FillRect einen etwas höheren Zeit- und Rechenaufwand benötigt und von daher das Flimmern kommt ? Wenn ich die Bitmap in ein TImage lade und dieses dann bewege, erhalte ich übrigens den gleichen Effekt. Mir stellt sich die Frage, ob ich mal versuchsweise die Grafik selbst zeichnen sollte ? Was natürlich mit einem ungeheuren Programmieraufwand verbunden ist, dazu habe ich eigentlich keine Lust und auch keine Zeit. Oder sollte ich die Malerarbeiten lieber der GPU überlassen, sofern die Nutzung von DirectX in Delphi überhaupt möglich ist ? Gruß, Andreas |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
Du solltest jegliche Grafikoperationen auf einem TBitmap durchführen und dann (z.B. mittels Draw) auf die Form kopieren. Außerdem würde ich Bild3 nicht jedes Mal neu laden, sondern in einem seperaten Bitmap speichern. Zusammen mit DoubleBuffered sollte es kein Flimmern mehr geben.
PS: Ein Timer wird niemals ein Intervall von einer Millisekunde schaffen, mit XP sind es höchstens circa 14 ms. Nimm am besten eine Endlosschleife und ProcessMessages. |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
Hallo,
eure Tipps haben leider alle keine Verbesserungen in der Darstellung bewirkt. Weder das DoubleBuffering noch die Kopie aller Bitmaps in je eine eigene Instanz. Ich habe das Projekt mal in eine ZIP gepackt (Simulation, ohne serielle Connection zur S5 !!!). Wäre schön, wenn jemand meinen vermeintlichen Fehler beseitigen könnte. Damit könnt ihr euch selbst am besten ein flimmerndes Bild davon machen. :wink: Download: ![]() Danke für weitere Hinweise. :-D Gruß, Andreas |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
nur mal so directX ist möglich in Delphi (such mal hier DelphiX etc)
weiß aber nicht ob es directX schon für Delphi 2005 gibt |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
Tipp von mir
Wenn man, z.B. eine Grafik mit einem Timer verschiebt, treten störende Flickereffekte auf. Kann ich das irgendwie abstellen? Ja das ist Möglich. 1. Die einfachste Möglichkeit ist es DoubleBuffered des Parents auf True setzen: Dazu ein kleines Beispiel:
Delphi-Quellcode:
btw.: TImage auf diese Wiese zuverwenden ist nicht gut.
var Form1: TForm1;
vx: Integer = 1;implementation {$R *.DFM} procedure TForm1.BitBtn1Click(Sender: TObject); begin Form1.DoubleBuffered:=True; end; procedure TForm1.Timer1Timer(Sender: TObject); begin Image1.Left:=Image1.Left +vx; if Image1.Left>ClientWidth - Image1.Width-1 then vx:=vx*-1; if Image1.Left<1 then vx:=vx*-1; end; 2. Man benutzt ein offscreen Bitmap. Also alles zeichnen erfolgt auf einem Hintergrundbild und wenn alles gezeichnet wurde wird das gesamte Bild auf den "Bildschirm" kopiert.
Delphi-Quellcode:
Wie man sieht ist diese Methode etwas aufwendiger allerding verbraucht ein TBItmap weniger Ressorcen als ein TImage und somit ist diese Methode schneller.
var Form1: TForm1;
vx: Integer = 1;implementation Backpuffer: TBitmap; Bild: TBitmap; bildleft,bildtop: integer; {$R *.DFM} procedure TForm1.BitBtn1Click(Sender: TObject); begin //Ein Bild erstellen mit der gleichen Grösse wie das Formular Backpuffer:= TBitmap.create; Backpuffer.width := self.width; Backpuffer.height:= self.height; Bild:= TBitmap.create; Bild.loadfromfile("c:\blabla.bmp"); Timer1.enable := true; end; procedure TForm1.Timer1Timer(Sender: TObject); begin Backpuffer.canvas.brush.color := clwhite; Backpuffer.canvas.rectangle(0,0,Backpuffer.width,Backpuffer.height) bildleft:=bildleft+vx; if bildleft>ClientWidth - bild.Width-1 then vx:=vx*-1; if bildleft<1 then vx:=vx*-1; BitBlt(Backpuffer.Canvas.Handle, bildleft, bildtop, Bild.Width, Bild.Height, Bild.canvas.handle, 0, 0, SRCCOPY);//Bild auf Backpuffer kopieren BitBlt(self.Canvas.Handle, 0, 0, Backpuffer.Width, Backpuffer.Height, Backpuffer.canvas.handle, 0, 0, SRCCOPY);//Backpuffer auf das Formular kopieren end; 3. Verhindern das der Hintergrund gelöscht wird.
Delphi-Quellcode:
Das Funktioniert aber nur bei TWinControl bei TGraphiccontrol kann man es mit ControlStyle := [csOpaque] versuchen.
type
TForm1 = class(TForm) procedure StopFlicker(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND; end; Procedure TForm1.StopFlicker(var Msg: TWMEraseBkgnd); begin Msg.Result := 1; end; Man kann sich das aber auf sparen indem man nicht die Methoden repaint, invalidate oder vergleichbare benutzt sondern die Methode in der gezeichnet wird direkt aufruft. |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
Hallo Andreas,
ich hatte mal ein ähnliches Problem und ähnliche Antworten erhalten. Auch bei mir hat DoubleBuffered nicht das Geringste geholfen. Sehr gut ging aber Folgendes: Als Basiskomponente eine TPaintBox verwenden. Darauf ein TBitmap legen (nicht sicher, ob das notwendig ist). Das neue Bild in ein TBitmap zeichnen und dieses per BitBlockTransfer in die (sichtbare) Bitmap auf der PaintBox kopieren. Das flimmert bei mir überhaupt nicht. Grüße Heiner ![]() |
Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie
Und genau so sollte man es auch machen ;). Ich hatte bei dieser Variante auch noch keinerlei Probleme mit Flickern.
\\edit: Eine PaintBox sollte nichtmal nötig sein - man kann ja auch direkt auf's Formular kopieren. Ob und welche Vor/Nachteile eine PB mit sich bringt weiss ich nicht. \\edit2: Mit der Graphics32-Library ( ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:34 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