Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Paintbox flackert (https://www.delphipraxis.net/141513-paintbox-flackert.html)

delphi-n 10. Okt 2009 12:48


Paintbox flackert
 
Hi!

Ich hab eine procedure "zeichnen". Sie wird alle 200 millisec aufgerufen.
Diese funktioniert auch, und ist folgendermaßen aufgebaut:


Delphi-Quellcode:
procedure TForm2.Zeichnen;
var x,y,z: integer;
begin
PaintBox1.Refresh; //löschen der Paintbox
    for z:=0 to 9 do //zeichen kleinerer Objekte (der hintergrund ist auf einem anderen Image)
    begin
        for x:=0 to 14 do
        begin
            for y:=0 to 14 do
            begin                      
            if Q[x,y,z]=1 then  
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+131+Aposz*15-Aposy*15+Ba, Image11.Picture.Graphic);
            if Q[x,y,z]=2 then  
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15+Bb, Image2.Picture.Graphic);
            if Q[x,y,z]=3 then  
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image3.Picture.Graphic);
            if Q[x,y,z]=4 then
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image4.Picture.Graphic);
            if Q[x,y,z]=5 then
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image5.Picture.Graphic);
            if Q[x,y,z]=6 then
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image7.Picture.Graphic);
            if Q[x,y,z]=7 then
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image8.Picture.Graphic);
            if Q[x,y,z]=8 then
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image9.Picture.Graphic);
            if Q[x,y,z]=9 then
            PaintBox1.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image10.Picture.Graphic);


            end;
        end;
    end;                      

end;
Leider flackert das alles (wegen der Zeit zwischen löschen und neu zeichnen).
Nun hatte ich gehört, dass es besser wär alles erstmal aufzubauen, und das fertige bild in ein image oder eine Paintbox zu kopieren.
Da die PaintBox aber kein Bildspeicher hat, habe ich ein Image genommen. Leider kommen fehler.



Delphi-Quellcode:
procedure TForm2.Zeichnen;
var x,y,z: integer;
begin
PaintBox1.Refresh; //löschen des paintbox-inhalts
Image14.Picture.Destroy; //löschen des Image-inhaltes
Image14.Canvas.Draw(0,0, Image1.Picture.Graphic);  //zeichnen des hintergrundes auf das image //hier kommt der Fehler s.u.
    for z:=0 to 9 do  //zeichen kleinerer objekte
    begin
        for x:=0 to 14 do
        begin
            for y:=0 to 14 do
            begin
            if Q[x,y,z]=1 then  
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+131+Aposz*15-Aposy*15+Ba, Image11.Picture.Graphic);
            if Q[x,y,z]=2 then  
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15+Bb, Image2.Picture.Graphic);
            if Q[x,y,z]=3 then  
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image3.Picture.Graphic);
            if Q[x,y,z]=4 then
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image4.Picture.Graphic);
            if Q[x,y,z]=5 then
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image5.Picture.Graphic);
            if Q[x,y,z]=6 then
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image7.Picture.Graphic);
            if Q[x,y,z]=7 then
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image8.Picture.Graphic);
            if Q[x,y,z]=8 then
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image9.Picture.Graphic);
            if Q[x,y,z]=9 then
            Image14.Canvas.Draw(PaintBox1.Left+224+Aposx*30-Aposz*15, PaintBox1.Top+152+Aposz*15-Aposy*15, Image10.Picture.Graphic);


            end;
        end;
    end;
 Image13.Canvas.Draw(0,0,Image14.Picture.Graphic); //kopieren des gesamtbildes auf das für den nutzer sichbare image
end;

diese fehler kommen:

Zitat:

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project1.exe ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: 'Zugriffsverletzung bei Adresse 42F82B68. Lesen von Adresse 42F82B68'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------




---------------------------
Project1
---------------------------
Zugriffsverletzung bei Adresse 42F82B68. Lesen von Adresse 42F82B68.
---------------------------
OK
---------------------------



---------------------------
Anwendungsfehler
---------------------------
Exception EExternalException in Modul Project1.exe bei 00A47501.

Externe Exception C000001D.


---------------------------
OK
---------------------------

Ich hoffe ihr könnt mir weiterhelfen.

Vielen Dank schon mal,
Delphi-n

DeddyH 10. Okt 2009 12:54

Re: Paintbox flackert
 
Das OnPaint-Ereignis ist Dir aufgefallen? Was könnte man dort wohl machen? Und
Delphi-Quellcode:
Image14.Picture.Destroy; //Destroy sollte niemals direkt aufgerufen werden
ist eine ganz schlechte Idee, damit löschst Du das enthaltene Grafik-Objekt, ohne es auf nil zu setzen, deshalb knallt es beim 2. Aufruf.

alleinherrscher 10. Okt 2009 12:56

Re: Paintbox flackert
 
Zitat:

Zitat von delphi-n
Hi!
Leider flackert das alles (wegen der Zeit zwischen löschen und neu zeichnen).

Was auch noch helfen könnte, ist doublebuffered:=true zu setzen.

turboPASCAL 10. Okt 2009 13:10

Re: Paintbox flackert
 
Ja könnte man, aber das hilft nicht im obigen Fall des Quelltextes.
Da gibt es so einige, sagen wir mal Fehlerlein.

Delphi-Quellcode:
var x,y,z: integer;
begin
PaintBox1.Refresh; //löschen der Paintbox
Ja, löschen in dem man die Paintbox dazu zwingt sich selbst neu zu Zeichnen.
Man nehme ein Canvas.Fillrect(PaintBoxX.Clientrect); und gut.

Delphi-Quellcode:
Image14.Picture.Destroy; //löschen des Image-inhaltes
Wie schon beschrieben, Image14.Free; //löschen des Image-Inhaltes wäre angebracht.

Besser noch folgendes:
Delphi-Quellcode:
if ASSIGNED(Image14) then Image1.Free;

Des weiteren würde ich mich von den Images verabschieden und gleich mit Bitmaps (TBitmap) arbeiten.
Hier wäre ein Delphi-Referenz durchsuchenOffscreenbitmap angebracht, auf das man alles vor zeichnet um es danach
anzuzeigen.

DeddyH 10. Okt 2009 13:16

Re: Paintbox flackert
 
Hier schnell ein Beispiel (hab mal eben Lazarus unter Win7 installiert :mrgreen:):
Delphi-Quellcode:
const Colors: array[0..3] of TColor = (clRed, clBlue, clYellow, clGreen);

procedure TForm1.FormPaint(Sender: TObject);
var tempBMP: TBitmap;
begin
  tempBMP := TBitmap.Create;
  try
    tempBMP.Width := 100;
    tempBMP.Height := 100;
    tempBMP.Canvas.Brush.Color := Colors[FIndex];
    tempBMP.Canvas.FillRect(Classes.Rect(0,0,tempBMP.Width, tempBMP.Height));
    BitBlt(self.Canvas.Handle,10,10,tempBMP.Width,tempBMP.Height,tempBMP.Canvas.Handle,0,0,SRCCOPY);
  finally
    tempBMP.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  inc(FIndex);
  if FIndex > High(Colors) then
    FIndex := Low(Colors);
  invalidate;
end;
[edit] FIndex ist ein privates Integer-Feld, bevor noch Fragen dazu kommen [/edit]

Luckie 10. Okt 2009 13:19

Re: Paintbox flackert
 
Das ist aber auch nur halb zu Ende gedacht. Das Beispiel aus der Code-Lib ist besser.

DeddyH 10. Okt 2009 13:21

Re: Paintbox flackert
 
Das Beispiel wird er auch sicherlich auf Anhieb kapieren.

turboPASCAL 10. Okt 2009 13:23

Re: Paintbox flackert
 
Zitat:

[edit] FIndex ist ein privates Integer-Feld, bevor noch Fragen dazu kommen [/edit]
:stupid:
Delphi-Quellcode:
var
  private FInteger: array [0..DeddyH] of integer;
:mrgreen:

Luckie 10. Okt 2009 13:25

Re: Paintbox flackert
 
Ja, das mag ja sein, aber es ist wieder nur so halb gar. Das nützt ihm ja auch nichts.

delphi-n 10. Okt 2009 13:36

Re: Paintbox flackert
 
Zitat:

Des weiteren würde ich mich von den Images verabschieden und gleich mit Bitmaps (TBitmap) arbeiten.
Hier wäre ein Delphi-ReferenzOffscreenbitmap angebracht, auf das man alles vor zeichnet um es danach
anzuzeigen.
wie könnte ich denn das obere Beispiel in das aus dem link einfügen? (die weißen kasten in dem roten brauch ich ja nicht)


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:26 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