Lazarus

Programming => Graphics and Multimedia => TAChart => Topic started by: kinlion on December 07, 2018, 06:40:30 am

Title: [SOLVED] value of hinttool.NearestGraphPoint.y is not exactly the original value
Post by: kinlion on December 07, 2018, 06:40:30 am
I add some LineSeries to a Chart, and show hint when mouse on a data point.
Similar to wp said in the post https://forum.lazarus.freepascal.org/index.php/topic,34723.0.html (https://forum.lazarus.freepascal.org/index.php/topic,34723.0.html)
I write:
Code: Pascal  [Select][+][-]
  1. procedure TfrmLTPlanManager.ChartToolset1DataPointHintTool1Hint(
  2.   ATool: TDataPointHintTool; const APoint: TPoint; var AHint: String);
  3. var
  4.   hinttool: TDataPointHintTool;
  5.   ser: TLineSeries;
  6. begin
  7.   hinttool := TDataPointHintTool(ATool);
  8.   ser := TLineSeries(hinttool.Series);     // this is the clicked series
  9.   if ser = nil then
  10.     exit;
  11.  
  12.   AHint := Format('%6d日 %s %.0n支',
  13.       [
  14.         trunc(hinttool.NearestGraphPoint.X),
  15.         ser.Title,
  16.         hinttool.NearestGraphPoint.y
  17.       ]);
  18. end;
  19.  

However, the hint value from hinttool.NearestGraphPoint.y is not the original value.

Why?
Title: Re: value of hinttool.NearestGraphPoint.y is not exactly the value been added
Post by: wp on December 07, 2018, 10:34:58 am
Oh, I was not aware of this. It is because the "NearestGraphPoint" is calculated back from the screen pixels of the data point which leads to some inaccuracies. I don't know why it is made like this, probably because the corresponding TDataPointTool method is very general and must work also for series which do not require discrete listed data (such as TFuncSeries).

A better way is to directly read the x,y values from the series or the chart source. If your data are stored in the internal listsource of the lineseries you can simply call ser.XValue[index] and ser.YValue[index] where index is the series point index returned by ther chart tool (ser.PointIndex):
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ChartToolset1DataPointHintTool1Hint(ATool: TDataPointHintTool;
  2.   const APoint: TPoint; var AHint: String);
  3. var
  4.   ser: TLineSeries;
  5.   index: Integer;
  6. begin
  7.   if (ATool = nil) or (ATool.Series = nil) then
  8.     AHint := ''
  9.   else begin
  10.     ser := TLineSeries(ATool.Series);
  11.     index := ATool.PointIndex;
  12.     AHint := Format('Series "%s":' + LineEnding + '  x = %.3f' + LineEnding + '  y = %.3f',
  13.       [ser.Title, ser.XValue[index], ser.YValue[index] ]);
  14.   end;
  15. end;  
If data are provided by an external chartsource you query them from there, again ATool.PointIndex is the index of the data point.

You wrote somewhere that you have the data in an array. Then you probably use a TUserDefinedChartSource to link to array to the series. In this case you can call the OnGetChartDataItem event handler to find the x,y values.
Title: Re: value of hinttool.NearestGraphPoint.y is not exactly the value been added
Post by: kinlion on December 07, 2018, 04:57:00 pm
A better way is to directly read the x,y values from the series or the chart source. If your data are stored in the internal listsource of the lineseries you can simply call ser.XValue[index] and ser.YValue[index] where index is the series point index returned by ther chart tool (ser.PointIndex):

ser.PointIndex helps to resolve the problem.
Thanks wp :)

btw, how to mark this topic as RESOLVED ?
Title: Re: value of hinttool.NearestGraphPoint.y is not exactly the value been added
Post by: wp on December 07, 2018, 05:17:57 pm
Edit the title of the first post and add "[SOLVED]" in front of the title.
TinyPortal © 2005-2018