Paintbox leeren
-
Hallöchen
ich hab die Forensuche auch schon benutzt, aber kam zu nichts.
Ich habe eine Paintbox die alle 1-150ms aktualisiert wird (einstellbar), und bei einem schnellen Timer flackert die Linie blöderweise.
Also folgender Ablauf:1. Neue Berechnung
2. Box wird geleert (mit Canvas->Rectangle() überlagert)
3. Linie wird gezeichnet
4. -> 1.
usw.Wie kann ich das Flackern vermeiden?
Vielen Dank im Voraus,
Sandro
-
Naja, ich würde etwas mit BeginPaint() und EndPaint() machen und InvalidateRect(). Siehe mal in der BCB-Hilfe nach.
Aber was hat der Titel des Beitrages mit deiner Frage zu tun?
-
Such mal nach Double Buffering...
-
danke, ich schau nachher mal nach wenn ich zu Hause bin...
ich suche nach alternativen Methoden, die Box zu leeren. Ich denke mal, es gibt bessere als nur ein Viereck darüberzulegen...
-
Eine PaintBox brauchst du nicht zu leeren (außer du willst den gesamten Hintergrund in einer eigenen Farbe). Ein Aufruf von paintBox->Invalidate() ruft automatisch ein Neuzeichnen der PaintBox hervor, so daß du in dem OnPaint-Ereignis nur noch die Linie zeichnen brauchst (ich hoffe mal ganz stark, du zeichnest NICHT direkt in der Timer-Methode!).
-
Th69 schrieb:
(ich hoffe mal ganz stark, du zeichnest NICHT direkt in der Timer-Methode!).
ich hab mein Invalidate() in der Timer-Methode... aber davon hört das Flackern ja auch nciht auf
-
Wie? Was? Das Problem ist doch schon gelöst?!?
Psychedelixx schrieb:
ich hab mein Invalidate() in der Timer-Methode... aber davon hört das Flackern ja auch nciht auf
DocShoe schrieb:
Such mal nach Double Buffering...
-
DocShoe schrieb:
Such mal nach Double Buffering...
Wie schon DocShoe geschrieben hat such mal nach Double Buffering bzw.
in der Hilfe unter Form->DoubleBuffered.Nur leider haben ein paar Komponenten paar Probleme damit wie z.B. TListView usw.
Deshalb kannst du auch ein Double Buffering selbst machen, indem du statt direkt
auf den Bildschirm zu zeichnen erst in ein TBitmap zeichnest und wenn du fertig bist das komplette Bitmap in die Paintbox malst.
-
VergissEs schrieb:
...Deshalb kannst du auch ein Double Buffering selbst machen, indem du statt direkt
auf den Bildschirm zu zeichnen erst in ein TBitmap zeichnest und wenn du fertig bist das komplette Bitmap in die Paintbox malst.Das habe ich jetzt getan... meine Linie flackert jetzt auch nciht mehr, aber mein Hintergrund dafür... ach ich zeige euch einfach mal meinen Code:
void TForm1::zeichne(){ Label_Pts->Caption = pts; // Hintergrund färben: ImageBuffer->Canvas->Brush->Color = clSilver; ImageBuffer->Canvas->Rectangle(0,0,721,561); // (wohin damit er immer da ist und nicht flackert?) ImageBuffer->Canvas->Pen->Color = clFuchsia; ImageBuffer->Canvas->Ellipse(nom.getPositionX()-2, nom.getPositionY()-2, nom.getPositionX()+3, nom.getPositionY()+3); ImageBuffer->Canvas->Pen->Color = clBlack; ImageBuffer->Canvas->Pen->Width = 5; ImageBuffer->Canvas->MoveTo(Pos[0].getPositionX(), Pos[0].getPositionY()); for(int i=0; i<Pos[0].size(); i++){ ImageBuffer->Canvas->LineTo(Pos[i].getPositionX(), Pos[i].getPositionY()); } } void __fastcall TForm1::PaintBox1Paint(TObject *Sender){ zeichne(); PaintBox1->Canvas->Draw(0, 0, ImageBuffer->Picture->Graphic); } void __fastcall TForm1::Timer1Timer(TObject *Sender){ //... PaintBox1->Invalidate(); //... }
-
VergissEs schrieb:
Nur leider haben ein paar Komponenten paar Probleme damit wie z.B. TListView usw.
Ja, unter anderem auch TPanel. Darauf die PaintBox und TPanel::DoubleBuffered = true. Das sollte eigentlich reichen. Auf dem Panel sollten sich alle zu zeichnenden Objekte befinden.
Ansonsten könnte es auch helfen, den ImageBuffer vorzubereiten, bevor die OnPaint aufgerufen wird.
-
inwiefern vorbereiten?
-
Psychedelixx schrieb:
... meine Linie flackert jetzt auch nicht mehr, aber mein Hintergrund dafür...
das Problem habe ich jetzt... "verkleinert", in dem ich eine Shape mit der Hintergrundfarbe der Paintbox in den Hintergrund gelegt habe. Dennoch flackert zwischendurch die Farbe des Formulars durch (aber weniger als vor dieser Maßnahme)... warum?
edit: ich korrigiere mich: die Shape machts nur noch schlimmer. So flackert die Linie auch wieder...
-
Psychedelixx schrieb:
inwiefern vorbereiten?
Indem du das Image bereits in der Timer-Routine zeichnest, bevor du überhaupt Invalidate aufrufst.
-
irgendwas mache ich falsch
der Hintergrund flackert viel weniger, aber immernoch ein bisschen...
also so mache ich es jetzt:
1. Berechnung
2. Zeichne in unsichtbares BufferImage
3. Kopiere von Image nach PaintBox (im OnPaint Ereignis)
--> wiederhole 1. - 3.Also der Hintergrund meines Formulars ist violett. Die Paintbox soll einen silbernen Hintergrund haben. Hat sie auch größtenteils, aber bei jedem Interrupt erscheint ein horizontaler violetter Streifen im Bild...
-
Überprüfe mal ob dein ImageBuffer auch die Größe hat von der PaintBox
//ImageBuffer->Width
//ImageBuffer->Height
Falls das Bitmap kleiner ist scheint natürlich der Hintergrund durch.
-
Ausserdem dürfte, da du jetzt ins Bitmap zeichnest, der Ablauf nicht mehr stimmen.
Die OnPaint-Methode der PaintBox braucht damit auch keinen Code.In OnTimer:
1. Berechnung
2. Zeichne in unsichtbares BufferImage
3. Kopiere von Image nach PaintBoxDu brauchst kein Invalidate, da der Timer ja jedesmal ein neues Bild zu PBox schiebt.
Warum lese ich immer Image? Du hast doch ein TBitmap ?
-
kpeter schrieb:
Ausserdem dürfte, da du jetzt ins Bitmap zeichnest, der Ablauf nicht mehr stimmen.
Die OnPaint-Methode der PaintBox braucht damit auch keinen Code.In OnTimer:
1. Berechnung
2. Zeichne in unsichtbares BufferImage
3. Kopiere von Image nach PaintBoxDu brauchst kein Invalidate, da der Timer ja jedesmal ein neues Bild zu PBox schiebt.
Warum lese ich immer Image? Du hast doch ein TBitmap ?
mein Held... natürlich, danke
sieht super aus.
Ich hab ein TImage... ist das schlecht?
-
Es ist letztendlich eine Resourcenfrage.
Wenn du das Image sowieso unsichtbar hältst, weil es nix anzeigen soll/braucht,
könntest du gleich ein TBitmap nehmen.
-
worin genau besteht denn der Unterschied?
-
TImage ist eine visuelle Komponente, die du zur Entwurfszeit aufs Formular ziehen kannst.
TBitmap ist hingegen eine nicht visuelle Klasse und wird zur Laufzeit erzeugt und gelöscht.
Das TImage kapselt weitere Klassen (TPicture, TGraphic) und auch ein TBitmap, um es halt zur Designzeit anzeigen zu können.Ein TBitmap nimmt man gern für grafische Operationen, die nicht über den Screen laufen müssen(Zwischenbitmaps).
Ums dir mal zu erleichtern, hier ein einfaches Beispiel zum Erzeugen eines TBitmap:
*.h
#include <stdlib.h> . . . private: Graphics::TBitmap* bmp; public: __fastcall TForm1(TComponent* Owner); __fastcall ~TForm1(void); // Destruktor
*.cpp
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { bmp = new Graphics::TBitmap; bmp->Width = 200; bmp->Height = 200; PaintBox1->Width = 200; PaintBox1->Height = 200; randomize(); } //--------------------------------------------------------------------------- __fastcall TForm1::~TForm1(void) { delete bmp; } //--------------------------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender) { bmp->Canvas->Brush->Color = clSilver; bmp->Canvas->Rectangle(0, 0, 200, 200); bmp->Canvas->Brush->Color = clRed; bmp->Canvas->Ellipse(random(100), random(100), 100 + random(100), 100 + random(100)); PaintBox1->Canvas->Draw(0, 0, bmp); } //---------------------------------------------------------------------------
-
ahhh vielen vielen Dank :)(auch allen anderen für die Bemühungen)