Page 1 of 1

"Clicked' method of a TLineSeries created dynamically

Posted: Mon Mar 23, 2009 11:30 pm
by 10045871
I want to click on a TLineSeries which is created dynamically (during runtime) in order to check its data and properties.

For a TLineSeries created in design time, I know how to do it, but for the runtime case, I don't know how to link the event to the TLinesSeries.

Could you provide an example about doing this ?

Thanking you in advance.

Patrick

Posted: Tue Mar 24, 2009 10:26 am
by yeray
Hi Patrick,

Here is an example:

Code: Select all

  private
    { Private declarations }
    procedure OnClickLine(Sender: TChartSeries; ValueIndex: Integer;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

//...

procedure TForm1.FormCreate(Sender: TObject);
var lineSeries: TLineSeries;
begin
  lineSeries := TLineSeries.Create(nil);
  Chart1.AddSeries(lineSeries);
  lineSeries.FillSampleValues(25);

  lineSeries.OnClick := OnClickLine;
end;

procedure TForm1.OnClickLine(Sender: TChartSeries; ValueIndex: Integer;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  Caption := 'Line clicked!!!';
end;

Thank you

Posted: Tue Mar 24, 2009 5:05 pm
by 10045871
Great. Thank you so much for your fast reply.

Patrick

How to know a line is clicked ?

Posted: Wed Mar 25, 2009 9:23 am
by 10045871
In the above example, you create a single procedure OnClickLine and assign the OnClick event of the dynamically created Line to that procedure. My difficulty is if I create many lines, always dynamically, and assign their OnClick events to a single OnClickLine procedure, and I want to click to select a line among others, I couldn't be able to process the line clicked, because I don't know what line is clicked.
If the clicked line has a "clicked" property, this will be fine. But I don't see such a property.
Would you have any solution ?
Thanking you in advance.

Patrick

Posted: Wed Mar 25, 2009 9:50 am
by yeray
Hi Patrick,

What TeeChart version are you using? In v8 there is a clicked method for series that returns -1 if the series hasn't been clicked and the order in the series' value list of the point clicked.

Also, why do you need the series' index in the clicked event when you have the series? You could assign the same event to all your series and when one of them is clicked, Sender in OnClickLine procedure is the series.

Anyway if you want to retrieve the index of the clicked line, here is another example:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  for i:=0 to 10 do
  begin
    Chart1.AddSeries(TLineSeries.Create(nil));
    Chart1[i].FillSampleValues(25);
    Chart1[i].OnClick := OnClickLine;
  end;
end;

procedure TForm1.OnClickLine(Sender: TChartSeries; ValueIndex: Integer;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  Caption := 'Line ' + inttostr(Chart1.SeriesList.IndexOf(Sender)) + ' clicked!!! ';
end;

Thank you

Posted: Wed Mar 25, 2009 12:01 pm
by 10045871
This works quite well. Thank you for your support.

Problem with CalcPosPoint

Posted: Wed Dec 21, 2011 11:14 pm
by 10045871
Hello,
I create a curve with the following commands:
SPKT_Ch0_curve:= TFastLineSeries.Create(nil);
SPKT_Ch0_curve.title:='SPKT channel 0'; SPKT_Ch0_curve.color:= SPKT_Ch0_color.brush.color;
SPKT_Ch0_curve.OnClick := SPKT_Chart_OnClickLine;
SPKT_Ch0_curve.FillSampleValues(SPKT_curve_length.value);
SPKT_Chart.AddSeries(SPKT_Ch0_curve);


then make running curve:
with SPKT_Ch0_curve do begin
tmpTch:=XValues[1]-XValues[0];
if (Count>SPKT_curve_length.value) then repeat Delete(count-1) until count<= SPKT_curve_length.value;
AddXY(XValues.First-tmpTch,SPKT_ADCin_V[0]); // SPKT_ADCin_V[0]: input from an analog to digital converter
end;


then make time measurement by clicking on the graphic:
procedure TImpedance.SPKT_ChartMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
SPKT_chart.Canvas.pen.color:= clRed;
SPKT_chart.Canvas.pen.mode:= pmCopy;
SPKT_chart.Canvas.brush.color:= clNone;
if SPKT_CursorsOn.tag=1 then begin // enable cursors
if SPKT_Chart_clickcount=0 then begin
SPKT_cursor1.X:= X; SPKT_cursor1.Y:= Y;
SPKT_cursor1.Xvalue:= SPKT_chart.BottomAxis.CalcPosPoint(X);
SPKT_cursor1.Yvalue:= SPKT_chart.LeftAxis.CalcPosPoint(Y);
SPKT_cursor1.plotted:= true;
end else if SPKT_Chart_clickcount=1 then begin
SPKT_cursor2.X:= X; SPKT_cursor2.Y:= Y;
SPKT_cursor2.Xvalue:= SPKT_chart.BottomAxis.CalcPosPoint(X);
SPKT_cursor2.Yvalue:= SPKT_chart.LeftAxis.CalcPosPoint(Y);
SPKT_cursor2.plotted:= true;
// plot rectangle
if SPKT_Chart_clickcount=1 then begin
SPKT_chart.Canvas.MoveTo(SPKT_cursor1.X,SPKT_cursor1.Y);
SPKT_chart.Canvas.lineto(SPKT_cursor2.X,SPKT_cursor1.Y);
SPKT_chart.Canvas.lineto(SPKT_cursor2.X,SPKT_cursor2.Y);
SPKT_chart.Canvas.lineto(SPKT_cursor1.X,SPKT_cursor2.Y);
SPKT_chart.Canvas.lineto(SPKT_cursor1.X,SPKT_cursor1.Y);
end;
if SPKT_zoom_zone.checked then begin
SPKT_Chart.leftaxis.automatic:= false; SPKT_autoaxis.checked:= SPKT_Chart.leftaxis.automatic;
SPKT_chart.leftaxis.minimum:= SPKT_cursor2.Yvalue;
SPKT_chart.leftaxis.maximum:= SPKT_cursor1.Yvalue;
end;
end;
end else begin // clear cursors

end;
end;


I use the procedure above for measuring the time between 2 clicked points on the graphic.
The problem is Xvalue:= SPKT_chart.BottomAxis.CalcPosPoint(X) does not indicate the order of the data points. I had to divide the difference between 2 differents Xvalues by 50 in order to obtain the exact difference in number of points.

Later, I tried to load new data on the Chart with these commands:
If OpenDialog1.Execute then begin
AssignFile(SPKT_readbck_file,OpenDialog1.filename);
Reset(SPKT_readbck_file);
SPKT_Ch0_curve.clear;
while not(eof(SPKT_readbck_file)) do begin
readln(SPKT_readbck_file,v0);
SPKT_Ch0_curve.AddY(v0);
end;
CloseFile(SPKT_readbck_file);
end; // end of browse file


This time, the ratio between the Xvalue given by the BottomAxis.CalcPosPoint(X) method is still different befor (ratio is no longer 50), so that time measurement is quite false.

Would you advice a method to obtain good values of the clicked points using CalcPosPoint(X) ?

Thank you in advance

Patrick
Sciensoria
email : info@sciensoria.fr
21/12/2011

Re: "Clicked' method of a TLineSeries created dynamically

Posted: Thu Dec 22, 2011 4:25 pm
by yeray
Hi Patrick,

There are some variables in your code snipped I can't know their values so I cannot run that code. However, I think I understand what you are doing. The following code does something similar:

Code: Select all

uses Series;

type
  MyPoint = class
    X, Y: Integer;
    XValue, YValue: Double;
  end;

var P1, P2: MyPoint;
    isFirst: Boolean;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.View3D:=false;

  Chart1.AddSeries(TFastLineSeries).FillSampleValues();

  isFirst:=true;
  P1:=MyPoint.Create;
  P2:=MyPoint.Create;
end;

procedure TForm1.Chart1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var XDiff: Double;
begin
  if isFirst then
  begin
    P1.X:=X;
    P1.Y:=Y;
    P1.XValue:=Chart1.Axes.Bottom.CalcPosPoint(X);
    P1.YValue:=Chart1.Axes.Left.CalcPosPoint(Y);
    Caption:='P1.X: ' + IntToStr(P1.X) + ', P1.Y: ' + IntToStr(P1.Y) + ', P1.XValue: ' + FormatFloat('#0.##', P1.XValue) + ', P1.YValue: ' + FormatFloat('#0.##', P1.YValue);
  end
  else
  begin
    P2.X:=X;
    P2.Y:=Y;
    P2.XValue:=Chart1.Axes.Bottom.CalcPosPoint(X);
    P2.YValue:=Chart1.Axes.Left.CalcPosPoint(Y);
    Caption:=Caption + ' - P2.X: ' + IntToStr(P2.X) + ', P2.Y: ' + IntToStr(P2.Y) + ', P2.XValue: ' + FormatFloat('#0.##', P2.XValue) + ', P2.YValue: ' + FormatFloat('#0.##', P2.YValue);

    XDiff:=Abs(P1.XValue-P2.XValue);
    Caption:=Caption + ' - XDiff: ' + FormatFloat('#0.##', XDiff)
  end;

  isFirst:=not isFirst;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
    diff: Double;
begin
  with Chart1[0] do
    for i:=0 to 25 do
    begin
      diff:=YValues.Range/10;
      Add(YValue[Count-1] + random*(diff) - diff/2);
    end;
end;
However, I'm not sure to understand this part:
Sciensoria wrote:The problem is Xvalue:= SPKT_chart.BottomAxis.CalcPosPoint(X) does not indicate the order of the data points. I had to divide the difference between 2 differents Xvalues by 50 in order to obtain the exact difference in number of points.
I'm not sure about why do you have to divide the difference by 50. You'll see in the example above the calculation of the difference looks correct, isn't it?
Even if you were working with DateTime in the XValues, they are actually doubles so the calculations should be the same, just the format function to output the result should vary.