(Verständnis-)Probleme mit TPaintbox bzw. TImage

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
mde2506
Beiträge: 5
Registriert: So 24. Apr 2016, 19:16

(Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von mde2506 »

Guten Abend,

ich habe vor Ewigkeiten mit Turbo Pascal und Delphi 1.0 programmiert und bin vor kurzem auf Lazarus gestossen, weil ich Lust hatte, wieder ein bisschen zu programmieren.
Meine Prozedur macht zum Teil was sie soll, einige Zeilen des Codes werden ignoriert.

Code: Alles auswählen

procedure TfrmHopALong.Zeichnen;
var i : LongInt; // Laufvariable
begin
  with pbxSpielfeld.Canvas do
    begin
      Pen.Color := clBlack;
      Pen.Width := 1;
      Brush.Color := clRed;
      FPlotX := Trunc(FCalcX + (FSpielfeldBreite/2));
      FPlotY := Trunc((FSpielfeldHoehe/2) - FCalcY);
      Rectangle(FPlotX, FPlotY, FPlotX + FOffset, FPlotY + FOffset);
    end;
  For i := 1 to FSchritte do
    begin
      FCalcXX := FCalcY - Sign(FCalcX) * Sqrt(Abs(FB * FCalcX - FC));
      // FCalcXX := FCalcY + Sign(FCalcX) * Abs(FB * FCalcX - FC);
      FCalcYY := FA - FCalcX;
      FCalcX := FCalcXX;
      FCalcY := FCalcYY;
      FPlotX := Trunc(FCalcX + (FSpielfeldBreite/2));
      FPlotY := Trunc((FSpielfeldHoehe/2) - FCalcY);
      //pbxSpielfeld.Canvas.Rectangle(FPlotX, FPlotY, FPlotX + FOffset, FPlotY + FOffset);
      pbxSpielfeld.Canvas.Pixels[FPlotX, FPlotY] := clBlack;
      StatusBar1.Panels[2].Text:=IntToStr(i); // *** wird ignoriert ***
      if ((FSchritte Mod 1000) = 0) then StatusBar1.Panels[2].Text := IntToStr(i); // *** wird ignoriert ***
    end;
end


Bei pbxSpielfeld handelt es sich um eine TPaintbox, die Prozedur wird über einen Button aufgerufen.

Das Zeichnen der Grafik funktioniert prinzipiell, aber was ich nicht verstehe: warum werden die beiden letzten Zeilen (unabhängig, wo diese in der Schleife stehen) in der Schleife ignoriert?
Nachdem die Schleife durchlaufen wurde, wird der Endwert korrekt in die Statuszeile eingetragen.

Ich habe das Programm auch schon mit einem TImage anstatt der TPaintbox getestet, da tritt das gleiche Phänomen auf. Zusätzlich habe ich dort das Problem, dass das komplette Bild erst nach dem kompletten Schleifendurchlauf dargestellt wird und ich somit keine "Live"-Darstellung habe, wie sich das Bild aufbaut.

Bin ich echt zu doof für Lazarus oder was mache ich falsch?

Gruß, Mario.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von theo »

Bau ein
Application.ProcessMessages
ein, dort wo du die Controls sofort updaten möchtest.

Auf Paintbox sollte man übrigens immer in OnPaint zeichnen, nicht in OnClick etc.
Zeichnen auslösen mit Invalidate.

mde2506
Beiträge: 5
Registriert: So 24. Apr 2016, 19:16

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von mde2506 »

Danke, werde ich mal ausprobieren.

mde2506
Beiträge: 5
Registriert: So 24. Apr 2016, 19:16

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von mde2506 »

Guten Morgen,

nachdem ich die lezten Tage leider keine Zeit hatte, habe ich mal die Tipps von theo probiert.
  1. Tipp 1: Wenn ich bei der Paintbox die Zeichenfunktion in das PaintEvent der Paintbox zeichne und über Klick mit Invalidate das Ganze anstoße, habe ich das gleiche Problem, wie bei der Verwendung von TImage -> das Bild wird erst dargestellt, wenn die Schleife komplett durchlaufen ist.
  2. Tipp 2: Einfügen von Application.ProcessMessages in die Zeichenroutine. Ich habs am Anfang, am Ende und an verschiedenen Positionen in der Schleife probiert -> alles ohne Erfolg.

Jetzt bin ich nochmal probehalber zu TImage zurückgegangen.
  1. Wenn ich die Zeichnen-Prozedur über einen Button aufrufe, wird das Bild gezeichnet, wenn die Schleife durchlaufen ist.
  2. Bringe ich ein Application.ProcessMessages ans Ende der Zeichnen-Prozedur ein, sieht man, wie die Pixel eingefärbt werden, aber es dauert SEHR viel länger und das Ergebnis sieht anders aus, als wenn ich A.PM weglasse. Farbwechselversuche und Ausgeben der Laufvariable funktionieren auch hier nicht.
  3. Wenn ich es auch hier über das PaintEvent von TImage laufen lasse, ist das Ergebnis identisch zu TPaintbox.

Gruß, Mario.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von theo »

Grundsätzlich sollte man heute einem Bild auf dem Bildschirm beim Zeichnen nicht mehr zusehen müssen.

Probiere doch mal eine schnellere Zeichenmethode, z.B.
http://wiki.freepascal.org/Developing_w ... ng_example

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von wp_xyz »

In die OnPaint-Routine gehören nur Zeichenroutinen, keine Application.ProcessMessages und kein Verändern einer anderen Komponente (Statusbar.Panels[].Text). Das kann leicht dazu führen, dass das Betriebssystem eine erneute Paint-Message in die Warteschlange einreiht, und schon bist du bei einem nicht mehr reagierenden Programm.

Wenn du einen animierten Bildaufbau willst (ab wozu das künstlich abbremsen wollen, wenn heutzutage die Graphik eh so schnell ist?), musst du in der Logik deines Programms an anderer Stelle dafür sorgen. Leider verrätst du viel zu wenig, was du machen willst, daher kann ich keine detaillierteren Vorschläge machen.

mde2506
Beiträge: 5
Registriert: So 24. Apr 2016, 19:16

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von mde2506 »

Erstmal schon vielen Dank für die Antworten.

Klar, die Rechner sind schnell genug, um das Endergebnis direkt darzustellen. Aber gerade in diesem speziellen Fall finde ich persönlich es nett, wenn man den "hüpfenden" Aufbau direkt verfolgen kann.
Was ich machen will, ist eigentlich eine relativ primitive Sache: http://www.mathematische-basteleien.de/huepfer.htm

Ich dachte, das wäre ein relativ einfacher Wiedereinstieg in Delphi bzw. in dem Falle in Lazarus. Da habe ich mich wohl geirrt und in den Jahren zuviel wieder vergessen :(

Gruß, Mario.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von wp_xyz »

Ich würde nicht direkt auf den Canvas der Paintbox zeichnen, sondern in ein Bitmap. Dieses Bitmap wird in der OnPaint-Routine der Paintbox auf die Paintbox gemalt. Desweiteres würde ich eine Routine "Bildaufbau" schreiben, in der deine Zeichnen-Routine aufgerufen wird - diese malt aber auf den Canvas des Bitmaps, nicht auf den der Paintbox. Bildaufbau wird mit einem ButtonClick aufgerufen. Die Zeichnen-Routine bekommt den oberen Wert z der i-Schleife als Parameter und wird in BildAufbau mit hochzählendem Parameter z immer wieder aufgerufen, so dass sich das Bild allmählich aufbaut.

Etwa so wie im Anhang.
Dateianhänge
hüpfer.zip
(2.75 KiB) 144-mal heruntergeladen

mde2506
Beiträge: 5
Registriert: So 24. Apr 2016, 19:16

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von mde2506 »

Yay, das ist im Prinzip genau das, was ich vorhatte. Besten Dank!

Ich werde mir den Quelltext in Ruhe anschauen und nachvollziehen, was du da gemacht hast, bevor ich mich an einer Erweiterung versuche.

Und auch die Alternative in Bezug auf Bildaufbau von theo werde ich mir anschauen.

Vorerst nochmals vielen Dank an beide an dieser Stelle und noch einen schönen Restsonntag.

Gruß, Mario.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von Warf »

Ganz dumme Frage, sollte es nicht statt StatusBar1.Panels[2].Text einfach StatusBar1.Panels[2].Caption sein?

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: (Verständnis-)Probleme mit TPaintbox bzw. TImage

Beitrag von wp_xyz »

Nein. Obwohl der Typ von TStatusPanel.Text ein TCaption ist. Irgendwo hatte ich einmal gelesen, der Unterschied zwischen Text und Caption wäre, dass ersteres einer Benutzereingabe entspräche (Edit.Text), letzteres nicht (Label.Caption), aber diese Unterscheidung scheint schon lange verlorengegangen zu sein.

Antworten