[SOLVED] Posible Bug lazarus / 31-LCL ---------------------------------------------------------------------- critter · 2018-07-04 09:01 I have created the following component, and I find that at run time I do not change the color assigned at design time if I do not indicate it by code. 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 unit TestPanel; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, ExtCtrls, Graphics; type   { TTestColor }   TTestColor = class(TPersistent)  private    FColor: TColor;    procedure SetColor(AValue: TColor);  published    property Color: TColor read FColor write SetColor;  end;   { TTestPanel }   TTestPanel = class(TCustomPanel)  private    FPanelColor: TTestColor;  protected  procedure Paint; override;  public     constructor Create(AOwner: TComponent); override;     destructor Destroy; override;  published   property PanelColor:  TTestColor read FPanelColor;     property Caption;  end; procedure Register; implementation procedure Register;begin  RegisterComponents('Misc',[TTestPanel]);end; { TTestPanel } procedure TTestPanel.Paint;begin  inherited Paint;  with Canvas do  begin    Font.Color := FPanelColor.Color;    TextOut(10,10, Caption);  end;end; constructor TTestPanel.Create(AOwner: TComponent);begin  inherited Create(AOwner);  FPanelColor := TTestColor.Create;end; destructor TTestPanel.Destroy;begin  FPanelColor.Free;  inherited Destroy;end; { TTestColor } procedure TTestColor.SetColor(AValue: TColor);begin  if FColor=AValue then Exit;  FColor:=AValue; end; end. Am I doing something wrong or is it a bug? ---------------------------------------------------------------------- Thaddy · 2018-07-04 09:15 First set {$M+} for RTTI information. On top of the unit. Second maybe also declare the Color property as stored. This should  force streaming of the property value. ---------------------------------------------------------------------- marcov · 2018-07-04 09:54 Quote from: Thaddy on July 04, 2018, 11:15:07 amFirst set {$M+} for RTTI information. On top of the unit. It should inherit that status from TPersistent which is declared $M+ ---------------------------------------------------------------------- Thaddy · 2018-07-04 10:10 I know but I have seen this before. I could work around it like above. No clue why. It may indeed be a bug. ---------------------------------------------------------------------- critter · 2018-07-04 10:16 I do not know if I am doing something wrong, but I have included the clause {$ M +} and it does not do what it is supposed to do. ---------------------------------------------------------------------- rvk · 2018-07-04 10:25 Quote from: critter on July 04, 2018, 11:01:01 amI have created the following component, and I find that at run time I do not change the color assigned at design time if I do not indicate it by code. This sentence doesn't quite flow correctly. I don't understand what your actual problem is. Is it when changing the color at design-time, that it doesn't change. Or doesn't it change during run-time? Anyway... You change the FColor in SetColor(). But it might be that the panel isn't repainted immediately. Maybe you should put a invalidate in there to make sure the panel is repainted. 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 TTestColor.SetColor(AValue: TColor);begin  if FColor=AValue then Exit;  FColor:=AValue;  Invalidate;end; ---------------------------------------------------------------------- critter · 2018-07-04 10:33 The problem is that I assign a color from the property editor at design time and when I execute it, it does not show me the selected color, but the default color. ---------------------------------------------------------------------- rvk · 2018-07-04 10:59 Quote from: critter on July 04, 2018, 12:33:06 pmThe problem is that I assign a color from the property editor at design time and when I execute it, it does not show me the selected color, but the default color. I take it you mean the font color. When I do this in design time the font color doesn't change directly. But if I move the panel the color did change. Try it... So you need to repaint the panel on changing the color. Because you used a sub-property you can't use Invalidate directly but you need to reach TTestPanel from TTestColor. (not sure how other than giving an owner to TTestColor and using Owner.Invalidate) Any reason you used a complete sub-property while you could have used a single FontColor property (in which you could call Invalidate). Are you planning to add more properties to TTestColor? ---------------------------------------------------------------------- Blaazen · 2018-07-04 11:13 Reason is that you declared it as a read-only property. It is not streamed to *.lfm. Add write part: 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   property PanelColor: TTestColor read FPanelColor write FPanelColor;//or  property PanelColor: TTestColor read FPanelColor write SetPanelColor; ---------------------------------------------------------------------- critter · 2018-07-04 11:19 Quote from: Blaazen on July 04, 2018, 01:13:00 pmReason is that you declared it as a read-only property. It is not streamed to *.lfm. Add write part: 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   property PanelColor: TTestColor read FPanelColor write FPanelColor;//or  property PanelColor: TTestColor read FPanelColor write SetPanelColor;  I tried it and it still does not save the color ---------------------------------------------------------------------- critter · 2018-07-04 11:21 Quote from: rvk on July 04, 2018, 12:59:06 pmQuote from: critter on July 04, 2018, 12:33:06 pmThe problem is that I assign a color from the property editor at design time and when I execute it, it does not show me the selected color, but the default color. I take it you mean the font color. When I do this in design time the font color doesn't change directly. But if I move the panel the color did change. Try it... So you need to repaint the panel on changing the color. Because you used a sub-property you can't use Invalidate directly but you need to reach TTestPanel from TTestColor. (not sure how other than giving an owner to TTestColor and using Owner.Invalidate) Any reason you used a complete sub-property while you could have used a single FontColor property (in which you could call Invalidate). Are you planning to add more properties to TTestColor? The code is just a test. The purpose is a panel in which different objects are drawn, all inherited from TPersistent. ---------------------------------------------------------------------- rvk · 2018-07-04 11:31 This works for me. It uses a single-property FontColor for changing the color of the caption-font. If you want to add more properties for the caption-font (like size and face) you want to revert back to a sub-property but then you still need to invalidate when one of the properties change. Maybe using SetTestColor() works. Otherwise TTestColor needs to have a parent so you can reach the panel from the TTestColor-class. 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 unit TestPanel; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, ExtCtrls, Graphics; type   { TTestPanel }   TTestPanel = class(TCustomPanel)  private    FFontColor: TColor;    procedure SetFontColor(AValue: TColor);  protected    procedure Paint; override;  public    constructor Create(AOwner: TComponent); override;    destructor Destroy; override;  published    property FontColor: TColor read FFontColor write SetFontColor;    property Caption;  end; procedure Register; implementation procedure Register;begin  RegisterComponents('Misc', [TTestPanel]);end; { TTestPanel } procedure TTestPanel.Paint;begin  inherited Paint;  with Canvas do  begin    Font.Color := FFontColor;    TextOut(10, 10, Caption);  end;end; constructor TTestPanel.Create(AOwner: TComponent);begin  inherited Create(AOwner);  FFontColor := clDefault;end; destructor TTestPanel.Destroy;begin  inherited Destroy;end; procedure TTestPanel.SetFontColor(AValue: TColor);begin  if FFontColor <> AValue then  begin    FFontColor := AValue;    Invalidate;  end;end; end. ---------------------------------------------------------------------- Blaazen · 2018-07-04 11:33 QuoteI tried it and it still does not save the color How did you test? Did you rebuild the IDE? ---------------------------------------------------------------------- critter · 2018-07-04 11:39 Currently the component is like this: 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 unit TestPanel;  {$mode objfpc}{$H+} interface uses  Classes, SysUtils, ExtCtrls, Graphics; type   TTestPanel = class;   { TTestColor }   TTestColor = class(TPersistent)  private    FColor: TColor;    FOwner: TTestPanel;    procedure SetColor(AValue: TColor);  published    constructor Create(AOwner: TComponent);    property Color: TColor read FColor write SetColor;  end;   { TTestPanel }   TTestPanel = class(TCustomPanel)  private    FPanelColor: TTestColor;  protected  procedure Paint; override;  public     constructor Create(AOwner: TComponent); override;     destructor Destroy; override;  published   property PanelColor:  TTestColor read FPanelColor write FPanelColor;     property Caption;     property Font;  end; procedure Register; implementation procedure Register;begin  RegisterComponents('Samples',[TTestPanel]);end; { TTestPanel } procedure TTestPanel.Paint;begin  inherited Paint;  with Canvas do  begin    Brush.Style := bsClear;    Font.Color := FPanelColor.Color;  TextOut(10,10, Caption);  end;end; constructor TTestPanel.Create(AOwner: TComponent);begin  inherited Create(AOwner);  FPanelColor := TTestColor.Create(Self);end; destructor TTestPanel.Destroy;begin  FPanelColor.Free;  inherited Destroy;end; { TTestColor } procedure TTestColor.SetColor(AValue: TColor);begin  if FColor=AValue then Exit;  FColor:=AValue;  FOwner.Invalidate;end; constructor TTestColor.Create(AOwner: TComponent);begin  inherited Create;  FOwner := AOwner as TTestPanel;end; end. Anyone can test if really in runtime changes the color assigned in design time? ---------------------------------------------------------------------- rvk · 2018-07-04 11:46 Quote from: critter on July 04, 2018, 01:39:44 pmAnyone can test if really in runtime changes the color assigned in design time? Yes, I had to comment out // procedure SetOtherColor(AValue: TColor); because you haven't included it (are you sure you are recompiling the IDE?). But when I drop a TestPanel on a form and change the PanelColor.Color in design-time to clRed, the caption turns red directly in the design- form. (I didn't need to move the panel this time for it to change) ---------------------------------------------------------------------- critter · 2018-07-04 11:50 Quote from: rvk on July 04, 2018, 01:46:28 pmQuote from: critter on July 04, 2018, 01:39:44 pmAnyone can test if really in runtime changes the color assigned in design time? Yes, I had to comment out // procedure SetOtherColor(AValue: TColor); because you haven't included it (are you sure you are recompiling the IDE?). But when I drop a TestPanel on a form and change the PanelColor.Color in design-time to clRed, the caption turns red directly in the design- form. (I didn't need to move the panel this time for it to change) the problem is in runtime ---------------------------------------------------------------------- rvk · 2018-07-04 11:54 Quote from: critter on July 04, 2018, 01:50:30 pmthe problem is in runtime Then you need to provide an example because this works fine too: 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.FormCreate(Sender: TObject);begin  TestPanel1.PanelColor.Color := clYellow;end; B.T.W. I take it FontColor is just an example because every TComponent (including TPanel) already has a TFont which you could use and which automatically redraws the complete component (with Invalidate internally). ---------------------------------------------------------------------- critter · 2018-07-04 12:21 I just solved it, and in case anyone needs it, the solution is to put the clause "stored True" to the declaration of the subcomponent. 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      property PanelColor:  TTestColor read FPanelColor stored True;   Thank you all ---------------------------------------------------------------------- Thaddy · 2018-07-04 12:29 That's what I expected ---------------------------------------------------------------------- Blaazen · 2018-07-04 13:12 Quote from: critter on July 04, 2018, 02:21:01 pmI just solved it, and in case anyone needs it, the solution is to put the clause "stored True" to the declaration of the subcomponent. 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      property PanelColor:  TTestColor read FPanelColor stored True;   Thank you all Nonsense. From Delphi manual:QuoteIf a property has no stored directive, it is treated as if stored True were specified. It is the same in Lazarus. Adding "stored True" does nothing. It is still read-only property. I just tried with TECSlider.Knob, which is also TPersistent descendant and this code: 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 property Knob: TECSliderKnob read FKnob stored True; //write FKnob; causes exactly the same troubles: design-time changes are not shown at run- time and property Knob is not in *.lfm at all. My guess is that you do changes in your code and you don't reinstall the component properly - with absolutely necessary rebuild of whole Lazarus IDE. ---------------------------------------------------------------------- Thaddy · 2018-07-04 14:19 @Blaazen Well, you have a lot more experience with writing components, for FPC that is... (you know I like and use them) but I have encountered this too and I am not a noob. Strange that this fixes it most of the time. Can still be a bug. ---------------------------------------------------------------------- rvk · 2018-07-04 14:22 At least in trunk I didn't need to add the stored: True. Maybe it's in certain circumstances that it happens. 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 object Form1: TForm1  Left = 256  Height = 240  Top = 210  Width = 320  Caption = 'Form1'  ClientHeight = 240  ClientWidth = 320  LCLVersion = '1.9.0.0'  object TestPanel1: TTestPanel    Left = 64    Height = 50  Top = 80    Width = 170    PanelColor.Color = clFuchsia    Caption = 'TestPanel1'  endend ---------------------------------------------------------------------- Thaddy · 2018-07-04 14:41 That's my guess too, but I can not narrow it down. ( I use trunk as fresh milk:daily builds) ---------------------------------------------------------------------- Blaazen · 2018-07-04 18:57 @ Thaddy: Yes, it can be a bug. However, my suspicion is that original poster does not rebuild IDE properly(i.e. Package->Open Recent Package->Compile&Install). Then can easily happen that Lazarus does not reflect changes in code. And the bug will come back when he will rebuild IDE in future. ---------------------------------------------------------------------- Windsurfer · 2018-07-04 20:38 I think there is something wrong with the run time for Windows 10 and Linux Mint. Just drop a button on a form and try the following code with the button color set to cldefault in the object browser. Nothing changes with Laz 1.8.4 or 1.8.5 (fixes) on a 64 bit PC. 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  Button1.color := clblue;end; procedure TForm1.FormActivate(Sender: TObject);begin  Button1.Color := clAqua;end; procedure TForm1.FormCreate(Sender: TObject);begin  Button1.Color := clRed;end; ---------------------------------------------------------------------- rvk · 2018-07-04 21:13 Isn't TButton an OS component for which you can't change the color like that? It should always reflect the theme color. At least on Windows it's like that. It's been discussed before and is not a.bug: https://forum.lazarus.freepascal.org/index.php?topic=36774.0