AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Flimmern bei bewegten Bitmaps für eine Prozessvisualisierung
Thema durchsuchen
Ansicht
Themen-Optionen

Flimmern bei bewegten Bitmaps für eine Prozessvisualisierung

Ein Thema von Andreas_R · begonnen am 5. Apr 2005 · letzter Beitrag vom 17. Aug 2005
Antwort Antwort
Seite 1 von 2  1 2      
Andreas_R

Registriert seit: 5. Apr 2005
Ort: Bremen
14 Beiträge
 
Delphi 2005 Professional
 
#1

Flimmern bei bewegten Bitmaps für eine Prozessvisualisierung

  Alt 5. Apr 2005, 20:46
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:
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;
Und noch zwei Screenshots:

http://www.tsm-factory.de/Delphi/Prozess_01.png

http://www.tsm-factory.de/Delphi/Prozess_02.png

Danke für eure Vorschläge.

Gruß,
Andreas
Win XP Pro, Delphi 2005 Professional, Intel P4 3,2 GHz, 1 GB RAM, ATi Sapphire Radeon X800XT PE (16 Pipelines), eigenes Fahrrad.
  Mit Zitat antworten Zitat
Benutzerbild von toms
toms
(CodeLib-Manager)

Registriert seit: 10. Jun 2002
4.648 Beiträge
 
Delphi XE Professional
 
#2

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 5. Apr 2005, 20:48
Hallo!


Setze die DoubleBuffered Eigenschaft der Form auf True.
Thomas
  Mit Zitat antworten Zitat
Benutzerbild von Sanchez
Sanchez

Registriert seit: 24. Apr 2003
Ort: Neumarkt Stmk
892 Beiträge
 
Delphi XE6 Enterprise
 
#3

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 5. Apr 2005, 20:51
Hallo Andreas,

Hast du schon die Eigenschaft DoubleBuffered vom Formular auf true gesetzt? Das sollte das flimmern unterdrücken.

grüße, daniel
Daniel
Testen ist feige!
  Mit Zitat antworten Zitat
Andreas_R

Registriert seit: 5. Apr 2005
Ort: Bremen
14 Beiträge
 
Delphi 2005 Professional
 
#4

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 6. Apr 2005, 19:48
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
Win XP Pro, Delphi 2005 Professional, Intel P4 3,2 GHz, 1 GB RAM, ATi Sapphire Radeon X800XT PE (16 Pipelines), eigenes Fahrrad.
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#5

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 6. Apr 2005, 19:57
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.
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Andreas_R

Registriert seit: 5. Apr 2005
Ort: Bremen
14 Beiträge
 
Delphi 2005 Professional
 
#6

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 7. Apr 2005, 19:57
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.

Download: hier

Danke für weitere Hinweise.

Gruß,
Andreas
Win XP Pro, Delphi 2005 Professional, Intel P4 3,2 GHz, 1 GB RAM, ATi Sapphire Radeon X800XT PE (16 Pipelines), eigenes Fahrrad.
  Mit Zitat antworten Zitat
Nicodius

Registriert seit: 25. Apr 2003
Ort: Graz
2.234 Beiträge
 
Delphi 2006 Architect
 
#7

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 7. Apr 2005, 21:12
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
Nico Müller
  Mit Zitat antworten Zitat
Gandalfus

Registriert seit: 19. Apr 2003
407 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 7. Apr 2005, 21:22
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:
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;
btw.: TImage auf diese Wiese zuverwenden ist nicht gut.

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:
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;
Wie man sieht ist diese Methode etwas aufwendiger allerding verbraucht ein TBItmap weniger Ressorcen als ein TImage und somit ist diese Methode schneller.

3. Verhindern das der Hintergrund gelöscht wird.
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    procedure StopFlicker(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND;
end;

Procedure TForm1.StopFlicker(var Msg: TWMEraseBkgnd);
begin
  Msg.Result := 1;
end;
Das Funktioniert aber nur bei TWinControl bei TGraphiccontrol kann man es mit ControlStyle := [csOpaque] versuchen.

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.
  Mit Zitat antworten Zitat
HeinerGrimm

Registriert seit: 13. Sep 2004
5 Beiträge
 
#9

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 7. Apr 2005, 22:54
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



http://www.wissenschaft-technik-ethik.de
  Mit Zitat antworten Zitat
Benutzerbild von dizzy
dizzy

Registriert seit: 26. Nov 2003
Ort: Lünen
1.932 Beiträge
 
Delphi 7 Enterprise
 
#10

Re: Flimmern bei bewegten Bitmaps für eine Prozessvisualisie

  Alt 7. Apr 2005, 23:04
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 ( www.g32.org ) sollte es auch sehr gut gehen. TImage32 aufs Formular, einen Layer darin für das zu bewegende Bild, und dann die Position des Layers verändern. Allerding bedarf grad die Einarbeitung in das ordentliche Verwenden von Layern etwas Zeit... aber dann läuft's schnell!
Fabian K.
INSERT INTO HandVonFreundin SELECT * FROM Himmel
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:31 Uhr.
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