[SOLVED] Can't understand canvas behaviour. lazarus / 39-Graphics ---------------------------------------------------------------------- Hopestation · 2022-02-23 11:41 Hi. I am using Lazarus Vesion#:2.0.8, FPC version 3.0.4, SVN revision 62944, x86_64-win32/win64. I want to draw some rectangles on a form containg arrays of other components. These should all appear when the form is created but they don't appear. I started a simple application with a form holding one button unit Unit1; {$mode objfpc}{$H+} interface uses   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls; type   { TForm1 }   TForm1 = class(TForm)     Button1: TButton;     procedure Button1Click(Sender: TObject);     procedure FormCreate(Sender: TObject);   private   public   end; var   Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin   Canvas.Pen.Color := clRed;   Canvas.Pen.Width := 1;   Canvas.Rectangle(5,25,100,125); end; procedure TForm1.Button1Click(Sender: TObject); begin   Canvas.Pen.Color := clblack;   Canvas.Pen.Width := 1;   Canvas.Rectangle(5,5,100,100); end; END. When the form opens only the button appears on the form. There is no red rectangle Clicking on the button produces the black rectangle. If I expand the form to fill the screen the rectangle disappears. Clicking on the button produces it again. When I return to the design size the recatangle disappears again. Why isn't the red rectsngle drawn when the form is created and why don't the black rectangles stay on the form when I change it's size? Thanks ---------------------------------------------------------------------- howardpc · 2022-02-23 11:53 Quote from: Hopestation on February 23, 2022, 12:41:28 pmWhy isn't the red rectsngle drawn when the form is created and why don't the black rectangles stay on the form when I change it's size? Repainting the form happens every time the form changes, such as when you first show it or subsequently resize it. To get custom painting to be done whenever the form is repainted (and not just once in response to a button click) you need to use the form's OnPaint event handler to do your custom drawing. ---------------------------------------------------------------------- Handoko · 2022-02-23 12:11 Common mistakes newbies do graphics on GUI: Do drawing in OnCreate event OnCreate is only for initialize variables not for painting or loading big data from disk. When in OnCreate event, the canvas have not been fully generated/initialized, so doing any painting on it now is useless. Do drawing on form's canvas only once See @howardpc explanation. This link below, especially in the graphics category has many demos for doing graphics: https://wiki.freepascal.org/Portal:HowTo_Demos Quote from: Hopestation on February 23, 2022, 12:41:28 pm... why don't the black rectangles stay on the form when I change it's size?For performance and memory efficient reasons the system does not automatically redraw or keep what have been drawn on the canvas when you resize the form, so you need to redraw it. You use OnPaint event for this case. Alternatively you can use TImage, because it has memory buffer to keep what have been drawn on its canvas, so it will automatically redraw it for you when needed. ---------------------------------------------------------------------- wp · 2022-02-23 13:21 When you draw something on the form canvas after a button click, the drawing is not persistent. Suppose that the user, after the click, goes to another application and drags its window over your form with the custom painting. When he later drags the window away from your form again, your form gets the command from the OS to redraw itself, buit it does not know of the custom painting - the code for it was in the button's OnClick event handler, but this has been executed a long time ago... The mechanism provided for custom drawing is based on the OnPaint event. This event fires whenever the form is requested to redraw itself. But then, when you want the drawing to appear after a button click, how is this done? You store the information what should be drawn in some variables and request the form to repaint itself. Do this by calling the method Invalidate which marks the form's canvas to be no longer valid, puts a redraw request into the applications message quere and finally the form is redrawn when the queued commands are executed, usually when the application is idle. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Button1Click(Sender: TObject);begin  FBlackRect := Rect(5, 5, 100, 100);  // FBlackRect is a TRect  FBlackRectVisible := true;         // FBlackRectVisible is a boolean variable indicating that the rect should be painted  Invalidate;                          // Request repainting of the formend; In the form's OnPaint event handler you put the code for the drawing: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormPaint(Sender: TObject);begin  if FBlackRectVisible then  begin    Canvas.Pen.Color := clBlack;    Canvas.Pen.Width := 3;    Canvas.Rectangle(FBlackRect);  end;  if FRedRectVisible then  begin  Canvas.Pen.Color := clRed;    Canvas.Pen.Width := 3;    Canvas.Rectangle(FRedRect);  end;end; See attachment. ---------------------------------------------------------------------- Hopestation · 2022-02-23 17:20 Thanks for all the replies.