Recent

Author Topic: Values of a custom component not updated in the property editor(TAChart involved  (Read 592 times)

CM630

  • Hero Member
  • *****
  • Posts: 1094
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/

I have a custom component, one of its properties is TPlotAreaSize.

Code: Pascal  [Select][+][-]
  1. TPlotAreaSize = class(TPersistent)
  2.   private
  3.     FParent: TControl;
  4.     procedure SetWidth(aValue: integer);
  5.     procedure SetHeight(aValue: integer);
  6.     function GetWidth : integer;
  7.     function GetHeight : integer;
  8.   public
  9.     constructor Create(aParent: TControl); virtual;
  10.   published
  11.     property Width: Integer read GetWidth write SetWidth;
  12.     property Height: Integer read GetHeight write SetHeight;
  13. end;
  14.  


The problem is that when I set the property of the control in the property editor during design time the SetWidth or SetHeight routines are executed, the desired change happens, but the old value is still displayed in the property editor.
So when the property editor loses focus, the previous value is sent again, and SetWidth or SetHeight is executed once again with the previous value (the one still visible in the property editor) so the change is undone.

Code: Pascal  [Select][+][-]
  1. procedure TPlotAreaSize.SetWidth(aValue: integer);
  2. var
  3.   NonPAWidth: integer;
  4. begin
  5.   if not ClipRectInitialized(TWaveformGraph(FParent).Chart.ClipRect) then Exit;
  6.   if aValue = TWaveformGraph(FParent).Chart.ClipRect.Width then exit;
  7.   NonPAWidth := TWaveformGraph(FParent).Width - TWaveformGraph(FParent).Chart.ClipRect.Width;
  8.   TWaveformGraph(FParent).Width := NonPAWidth + aValue;
  9.     //I tried if any of the next 3 wlines will help, but they do not.
  10.     {TWaveformGraph(FParent).Invalidate;
  11.      TWaveformGraph(FParent).Chart.Invalidate;
  12.      TWaveformGraph(FParent).Width := NonPAWidth + aValue;}
  13.   //Showmessage ('SetWidth');
  14. end;  
  15.  


If I type the new value twice in the property editor the change happens as it should.
Or if I add the Showmessage ('SetWidth'); line, the SetWidth is not invoked for a second time and the change also happens as it should.
Any idea how to fix that?
I cannot use variables instead of GetWidth and GetHeight because these values are calculated dynamically and might be changed by another component of the control.

These are GetWidth and GetHeight:
Code: Pascal  [Select][+][-]
  1. function TPlotAreaSize.GetWidth: integer;
  2. begin
  3.   //TWaveformGraph(FParent).Chart.Invalidate; //This line does not help
  4.   Result := TWaveformGraph(FParent).Chart.ClipRect.Width;
  5. end;
  6.  
  7.  
  8. function TPlotAreaSize.GetHeight: integer;
  9. begin
  10.   //TWaveformGraph(FParent).Chart.Invalidate; //This line does not help
  11.   Result := TWaveformGraph(FParent).Chart.ClipRect.Height;
  12. end;


Chart is a TAChart.
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

wp

  • Hero Member
  • *****
  • Posts: 11993
I think the problem is that the "plotarea" size (plotarea = size of the rectangle spanned by the axes?) is not a free parameter in TAChart. It is calculated from other quantities: the size of the axis title font, the size of the axis labels font, the orientation of the axis labels, the length of the axis labels, some distances etc. In my eyes there is only the LabelSize property which could be used to tune the width of the plot area - see the drawing in the wiki (https://wiki.lazarus.freepascal.org/TAChart_documentation#Graphical_explanation). Your code, however, does not touch this.

Further complication regarding the plot area width originates from the right side of the chart when the last bottom axis label is so long that it reaches out of the axis range. I cannot remember exactly, but I think I had to add a dummy right axis to get a non-moving right chart side when data change.

CM630

  • Hero Member
  • *****
  • Posts: 1094
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
SetHeight and SetWidth works. If there is a calculation issue, it is not significant.
The problem is that they do not work from the first time.
I am not sure that the problem is rooted in TAChart, or there is something else.
Maybe GetWidth gets executed before TAChart performs the calculations.

But if it was the case, maybe TWaveformGraph(FParent).Chart.Invalidate; should solve the issues but it does not.
Code: Pascal  [Select][+][-]
  1. function TPlotAreaSize.GetWidth: integer;
  2. begin
  3.  //TWaveformGraph(FParent).Chart.Invalidate; //This line does not help
  4.   Result := TWaveformGraph(FParent).Chart.ClipRect.Width;
  5. end;



As I said, a Showmessage ('SetWidth') in the end of SetWidth solves the issue, unfortunately, the control is not usable with a Showmessage.

A Sleep() does not help.
So I guess that Showmessage forces some update of the IDE, and if I can force it another way, this could be the solution.
« Last Edit: April 16, 2024, 12:11:08 pm by CM630 »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

wp

  • Hero Member
  • *****
  • Posts: 11993
Now I understand a bit more what you want to achieve.

TAChart starts with the size given to it by its Width and Height properties. Then, in the Draw method (which is called from the Paint cycle), it does all its internal size calculations to fit all its elements into this given rectangle. The ClipRect is only known afterwards. So, I think you can solve your issues by FIRST forcing the chart to draw itself; but don't call Chart.Invalidate which is delayed and not executed immediately; Chart.Refresh maybe should do.


CM630

  • Hero Member
  • *****
  • Posts: 1094
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Thanks, TWaveformGraph(FParent).Chart.Refresh in
Code: Pascal  [Select][+][-]
  1. function TPlotAreaSize.GetWidth: integer;
  2. begin
  3.   TWaveformGraph(FParent).Chart.Refresh;
  4.   Result := TWaveformGraph(FParent).Chart.ClipRect.Width;
  5. end;
seems to solve the issue!
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

 

TinyPortal © 2005-2018