Reputation: 27
I am developing an application on Embarcadero XE where i receive real time data from the ethernet port and display on a teechart chart on the screen.
The application works like an osciloscope, that is, there is a time window (10 seconds for example) of data that the chart displays, and each new incoming point overwrites what already is on screen.
I would like your help to make a code that puts a marker on only the newest point added, so the user can keep track of which of the points on the screen is the most recent point. I don´t want all of the points with a marker, i want only the newest.
The series being used is a fastline.
Here is the code i'm using to add data to the chart:
//Delete already existing point
if (Oscilografia.Series[0].Count>1) then
begin
Oscilografia.Series[0].Delete(cont);
end;
//Write point
Oscilografia.Series[0].addxy(cont,data, '', clblue);
Upvotes: 1
Views: 5090
Reputation: 5039
As an alternative to J's proposal of using custom drawing techniques to draw a pointer, you could change the TFastLineSeries
to use a TLineSeries
and make its Pointer Visible. Then, you can use OnGetPointerStyle
event to hide all the pointers except the last one:
uses Series;
var Series1: TLineSeries;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
Chart1.View3D:=false;
Series1:=Chart1.AddSeries(TLineSeries) as TLineSeries;
for i:=0 to 360 do
Series1.Add(Sin(PI*i/180));
Series1.Pointer.Visible:=true;
Series1.OnGetPointerStyle:=SeriesGetPointerStyle;
end;
function TForm1.SeriesGetPointerStyle(Sender:TChartSeries; ValueIndex:Integer):TSeriesPointerStyle;
begin
result:=(Sender as TLineSeries).Pointer.Style;
if (ValueIndex<>Sender.Count-1) then
result:=psNothing;
end;
And as a complement, if you want to show the Mark of the last point in the series, you can make the series' Marks Visible and use OnGetMarkText
event to hide all the Marks except the last one:
uses Series;
var Series1: TLineSeries;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
Chart1.View3D:=false;
Series1:=Chart1.AddSeries(TLineSeries) as TLineSeries;
for i:=0 to 360 do
Series1.Add(Sin(PI*i/180));
Series1.Pointer.Visible:=true;
Series1.OnGetPointerStyle:=SeriesGetPointerStyle;
Series1.Marks.Visible:=true;
Series1.OnGetMarkText:=SeriesGetMarkText;
end;
function TForm1.SeriesGetPointerStyle(Sender:TChartSeries; ValueIndex:Integer):TSeriesPointerStyle;
begin
result:=(Sender as TLineSeries).Pointer.Style;
if (ValueIndex<>Sender.Count-1) then
result:=psNothing;
end;
procedure TForm1.SeriesGetMarkText(Sender:TChartSeries; ValueIndex:Integer; var MarkText:String);
begin
if (ValueIndex<>Sender.Count-1) then
MarkText:='';
end;
Note I'm using a TLineSeries
here also, but if you are only interested on showing the Marks and not the Pointer, you can still use a TFastLineSeries
.
Upvotes: 1
Reputation: 31403
You have several options. The simplest is to make a new TPointSeries
to display the current point. If you wish to not show this series in the legend then simply set :
Oscilografia.Series[n].ShowInLegend := false;
where n
is the index of the series you wish to exclude from the legend.
Alternatively, you can custom-draw any relevant items in the OnAfterDraw
handler. For example :
procedure TForm1.Chart1AfterDraw(Sender: TObject);
var
xPos, yPos : integer;
begin
Chart1.Canvas.Pen.Color := clRed;
Chart1.Canvas.Pen.Style := psSolid;
Chart1.Canvas.Pen.Width := 1;
Chart1.Canvas.Pen.Mode := pmCopy;
xPos := Chart1.BottomAxis.CalcPosValue(CurrentXValue);
yPos := Chart1.LeftAxis.CalcPosValue(CurrentYValue);
// Parameters are
// X-Coord, Y-Coord, X-Radius, Y-Radius, Start Angle, End Angle, Hole%
Chart1.Canvas.Donut(xPos, yPos, 3, 3, 0, 360, 0);
end;
This produces, for example :
Custom drawing lets you do other things also, like add markers, etc. For example :
procedure TForm1.Chart1AfterDraw(Sender: TObject);
var
xPos, yPos : integer;
yMax, yMin : integer;
begin
Chart1.Canvas.Pen.Color := clRed;
Chart1.Canvas.Pen.Style := psSolid;
Chart1.Canvas.Pen.Width := 1;
Chart1.Canvas.Pen.Mode := pmCopy;
xPos := Chart1.BottomAxis.CalcPosValue(CurrentXValue);
yPos := Chart1.LeftAxis.CalcPosValue(CurrentYValue);
Chart1.Canvas.Donut(xPos, yPos, 3, 3, 0, 360, 0);
Chart1.Canvas.Pen.Color := clGreen;
Chart1.Canvas.Pen.Style := psDash;
yMax := Chart1.LeftAxis.CalcPosValue(Chart1.LeftAxis.Maximum);
yMin := Chart1.LeftAxis.CalcPosValue(Chart1.LeftAxis.Minimum);
Chart1.Canvas.DoVertLine(xPos, yMax, yMin);
end;
Which gives a dashed vertical line that follows the current point :
Note that the CalcPosValue
function is exposed by the chart axes and allows you to translate a point in the axis-space to an integer (screen) coordinate in the chart's canvas space.
Upvotes: 5