Recent

Author Topic: [SOLVED] tcustomcontrol and paint  (Read 8488 times)

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
[SOLVED] tcustomcontrol and paint
« on: August 24, 2017, 12:22:26 pm »
I am developing a control derived from TCustomControl
I draw customly my control.
My control works well on win and linux but I have refreshing problems on osx.
Here a simple code reproducing this behaviours.
A form with a tcheckbox, when I change the checkbox selection I would like to change my control color.
Why it does not work on osx? What I am doing wrong?

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TMyDrawingControl }
  13.  
  14.   TMyDrawingControl = class(TCustomControl)
  15.   private
  16.     FRedGrid: boolean;
  17.     procedure SetRedGrid(AValue: boolean);
  18.   public
  19.     procedure Paint; override;
  20.     property RedGrid: boolean read FRedGrid write SetRedGrid;
  21.   end;
  22.   { TForm1 }
  23.  
  24.   TForm1 = class(TForm)
  25.     CheckBox1: TCheckBox;
  26.     MyDrawingControl: TMyDrawingControl;
  27.     procedure CheckBox1Change(Sender: TObject);
  28.     procedure Edit1Change(Sender: TObject);
  29.     procedure FormCreate(Sender: TObject);
  30.     procedure FormDestroy(Sender: TObject);
  31.   private
  32.     { private declarations }
  33.   public
  34.     { public declarations }
  35.   end;
  36.  
  37. var
  38.   Form1: TForm1;
  39.  
  40. implementation
  41.  
  42. {$R *.lfm}
  43.  
  44. procedure TMyDrawingControl.SetRedGrid(AValue: boolean);
  45. begin
  46.   if FRedGrid=AValue then Exit;
  47.   FRedGrid:=AValue;
  48.   Paint;
  49. end;
  50.  
  51. procedure TMyDrawingControl.Paint;
  52. var
  53.   x, y: Integer;
  54. begin
  55.   // Draws the background
  56.   Canvas.Pen.Color := clWhite;
  57.   Canvas.Rectangle(0, 0, Width, Height);
  58.  
  59.   // Draws squares
  60.   if RedGrid then
  61.      Canvas.Pen.Color := clRed
  62.   else
  63.     Canvas.Pen.Color := clBlack;
  64.   for x := 1 to 8 do
  65.     for y := 1 to 8 do
  66.       Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8),
  67.         Round(x * Width / 8), Round(y * Height / 8));
  68.  
  69.   inherited Paint;
  70. end;
  71. { TForm1 }
  72.  
  73.  
  74. procedure TForm1.CheckBox1Change(Sender: TObject);
  75. begin
  76.   MyDrawingControl.RedGrid:= CheckBox1.Checked;
  77. end;
  78.  
  79. procedure TForm1.FormCreate(Sender: TObject);
  80. begin
  81.   MyDrawingControl := TMyDrawingControl.Create(Self);
  82.   MyDrawingControl.Align := alClient;
  83.   MyDrawingControl.Parent := Self;
  84.   MyDrawingControl.DoubleBuffered := True;
  85.   MyDrawingControl.RedGrid:= True;
  86.   CheckBox1.Checked:= True;
  87. end;
  88.  
  89. procedure TForm1.FormDestroy(Sender: TObject);
  90. begin
  91. end;
  92.  
  93. end.
  94.  
« Last Edit: August 25, 2017, 03:26:03 pm by apeoperaio »

zeljko

  • Hero Member
  • *****
  • Posts: 1594
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: tcustomcontrol and paint
« Reply #1 on: August 24, 2017, 12:41:57 pm »
As I can see you're painting outside of paint event. eg inside SetRedGrid() call Update() or Repaint() instead of Paint().

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: tcustomcontrol and paint
« Reply #2 on: August 24, 2017, 01:09:37 pm »
Invalidate; should be enough.
Code: Pascal  [Select][+][-]
  1. procedure TMyDrawingControl.SetRedGrid(AValue: boolean);
  2. begin
  3.   if FRedGrid=AValue then Exit;
  4.   FRedGrid:=AValue;
  5.   Invalidate;
  6. end;
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: tcustomcontrol and paint
« Reply #3 on: August 24, 2017, 02:39:34 pm »
Invalidate works as expected.
But what does it means that I am painting outside paint event?
I inherited Paint method for drawing (all drawings are performed in paint procedure), then I call paint method, if necessary (e.g. some drawing settings changed).
What shoould I do to paint inside paint event?

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: tcustomcontrol and paint
« Reply #4 on: August 24, 2017, 04:32:12 pm »
Invalidate works on windows and osx but not on linux.
I tried paint, invalidate and update. None works.
The problem is different from the previous one.
If I change the checkbox value the grid color is updated but if I resize the form, the new grid is painted over the previous one.
See attached screenshot

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: tcustomcontrol and paint
« Reply #5 on: August 24, 2017, 05:07:47 pm »
If I change the checkbox value the grid color is updated but if I resize the form, the new grid is painted over the previous one.
You have that backwards. From what I can see you have a secondary paint process that is not aware of the size change and it runs after the size aware drawing has finished.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: tcustomcontrol and paint
« Reply #6 on: August 24, 2017, 05:12:14 pm »
So, what I have to do to correctly paint my customcontrol?

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: tcustomcontrol and paint
« Reply #7 on: August 24, 2017, 05:19:16 pm »
I haven't looked at the code posted in the first post yet, my conclusions come from the screenshot alone, if the code posted is the complete code that creates the screenshot I'll take a look a bit later, if not start with posting the complete code that produced your screenshot.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: tcustomcontrol and paint
« Reply #8 on: August 24, 2017, 05:37:09 pm »
Yes, in the first post I pasted the whole source code of my sample form.
Line 48 I tried changing with invalidate, repaint, update.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: tcustomcontrol and paint
« Reply #9 on: August 24, 2017, 06:55:28 pm »
I have build the code with lazarus 1.4.4 on open suse 13.2 (harlequin)(i586) for gtk2 replacing the call to paint with invalidate and everything works as expected see attached screenshot. So I have to ask for your versions for
1) linux
2)GTK
3)lazarus
4)FPC
if you have a default lazarus installation linux users might guess the fpc version the rest are mandatory. I'm sorry I do not have any newer linux distro installed to check farther
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: tcustomcontrol and paint
« Reply #10 on: August 24, 2017, 07:01:32 pm »
The point is that you cannot call Paint; directly (at least on Qt and Mac). All repainting is processed internally, Paint; is called by LCL (and widgetset) when needed. And when you call Invalidate; Update; Refresh; or Repaint; you are telling to LCL (and widgetset) that it IS needed.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: tcustomcontrol and paint
« Reply #11 on: August 24, 2017, 07:19:48 pm »
Ok, get the point about painting.
Using invalidate it works on mac (and win).
Anyway I got unexpected behaviour using linux:
Virtualbox with Ubuntu 16.10 64bit
lazarus 1.6.2 fpc 3.0.0


apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: tcustomcontrol and paint
« Reply #12 on: August 24, 2017, 07:30:25 pm »
same behaviour laz 1.4.4 fpc 2.6.4 virtual box ubuntu

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: tcustomcontrol and paint
« Reply #13 on: August 24, 2017, 07:43:52 pm »
it looks like partial redraw based on the area that GTK things it needs redrawing, an old region trick used extensively on windows. Just in case there is an lcl bug somewhere try setting doublebuffered to false
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   MyDrawingControl := TMyDrawingControl.Create(Self);
  4.   MyDrawingControl.Align := alClient;
  5.   MyDrawingControl.Parent := Self;
  6.   MyDrawingControl.DoubleBuffered := False;//This has changed.
  7.   MyDrawingControl.RedGrid:= True;
  8.   CheckBox1.Checked:= True;
  9. end;
  10.  

EDIT:
Sorry about that but since I can't run my own tests I'm just dropping ideas here for testing.
first it looks like you have a problem with resize so the paint;/invalidate call in the oncheckboxchange event should not have any effect. Try after resizing changing the value on the checkbox and see if that solves the problem.
If it does then override the setbounds method and call invalidate after the call to inherited.
« Last Edit: August 24, 2017, 08:11:22 pm by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

apeoperaio

  • Sr. Member
  • ****
  • Posts: 272
Re: tcustomcontrol and paint
« Reply #14 on: August 25, 2017, 10:38:05 am »
DoubleBuffered True/False has no effect.
The problem is related to resize, and yes changing the checkbox value solves the problem.
I overrided the setbounds method adding invalidate after the call to inherited and now it works properly on win/mac/linux.

Is it a bug? Or is it the correct behaviour? Why Linux acts differently?

 

TinyPortal © 2005-2018