![]() |
This chapter documents how to manipulate Series and how to manipulate Series points and other Series internal data.
Note: Advanced. Series and values code is mainly located at TEENGINE.PAS unit.
Topics in this section:
Changing the Series Z order at runtime
Retrieving and modifying Points
Changing the Series type at runtime - Advanced
Series can be created at runtime just as like any other Delphi component:
First you need a Series variable:
Var MySeries : TBarSeries ;
{Then create the component:}
MySeries := TBarSeries.Create( Self );
{And then assign it to the desired Chart component:}
MySeries.ParentChart := Chart1 ;
{Now you can add points to MySeries or do whatever you can do with a design-time created Series.}
Shortcut:
{If you don’t need access to MySeries, the above code can be reduced to just one line of code:}
Chart1.AddSeries( TBarSeries.Create( Self ) );
{Class references:
Or you can use a Series class reference:
First declare the Series class variable:}
Var MyClass : TChartSeriesClass;
{Then set the desired Series class type:}
MyClass := TBarSeries ;
{Now you can create the Series component:}
Chart1.AddSeries( MyClass.Create( Self ) );
Chart components store all Series in SeriesList property, a Delphi TList object.
You have read-only access to this list in three ways:
A) Using the SeriesList property:
MySeries := Chart1.SeriesList [ 0 ]
B) Using the Series array property:
MySeries := Chart1.Series [ 0 ]
C) Or using the Chart1 default property:
MySeries := Chart1 [ 0 ]
Either way does the same.
The Chart1.SeriesCount property returns the number of Series in the SeriesList.
You can use SeriesCount to traverse all Chart Series:
for t := 0 to Chart1.SeriesCount - 1 do
With Chart1.Series [ t ] do
begin
SeriesColor := clBlue ;
end;
Series can be hidden in three ways:
A) Setting the Series Active property:
Series1.Active := False ;
B) Removing the Series from their parent Chart:
Series1.ParentChart := nil;
C) Destroying the Series completely:
Series1.Free ;
Changing the Series Z order at runtime.
In 3D mode (when Chart1.View3D is True ), all Series are assigned a Z order position. That is, the order where Series will be drawn, starting with the far most Series on the Chart 3D space.
You can control the order Series will be drawn, using these methods:
Chart1.ExchangeSeries( 0, 1 );
or...
Chart1.SeriesUp( Series1 );
Chart1.SeriesDown( Series1 );
The Series.ZOrder integer property returns the corresponding Z position for the Series.
Some Series in certain modes share the same ZOrder, like Stacked BarSeries. You can check if more than one Series has the same Z order using these functions:
if Series1.FirstInZOrder then .....
if Series1.MoreSameZOrder then .....
Every Series type has, at least, 2 values for each point. These values are designed as X and Y point co-ordinates.
Note: Values are defined as “Double” floating point variables.
Extended Series types have more than 2 values, like BubbleSeries has X, Y and Radiusvalues for each point.
So, each Series type has its appropriate method to add points, although the most common Series types like Line, Bar, Point and Area share the generic AddY method to add points.
The following code empties a TPieSeries and adds some sample values to it:
Series1.Clear ;
Series1.Add( 1234, ‘USA’, clBlue );
Series1.Add( 2001, ‘Europe’, clRed );
For extended Series types, please refer to each specific Series reference to know which method should be used to add points.
The Series AddArray method can be used in some situations:
Series3.Clear;
Series3.AddArray([ 1234, 2001, 4567.12 ] );
AddArray does not Clear the Series before adding points.
You can express points as constants or variables:
Series3.AddArray([ Table1Sales.AsFloat, 123, MyTotal ] );
To add an array of data to a Chart Series simply allocate the array to the Series.
Example
procedure TDynArrays.Button1Click(Sender: TObject);
Var X,Y : Array of Double; // TChartValues
t : Integer;
Num : Integer;
begin
{ number of points here using an Editbox to set Array size}
Num:=StrToInt(Edit1.Text);
{ allocate our custom arrays }
SetLength(X,Num);
SetLength(Y,Num);
{ fill data in our custom arrays }
X[0]:=0;
Y[0]:=Random(10000);
for t:=1 to Num-1 do
begin
X[t]:=t;
Y[t]:=Y[t-1]+Random(101)-50;
end;
{ set our X array }
With Series1.XValues do
begin
Value:=TChartValues(X); { <-- the array }
Count:=Num; { <-- number of points }
Modified:=True; { <-- recalculate min and max }
end;
{ set our Y array }
With Series1.YValues do
begin
Value:=TChartValues(Y);
Count:=Num;
Modified:=True;
end;
Chart1.UndoZoom; { <-- remove zoom (optional) }
{ Show data }
Series1.Repaint;
end;
In some circumstances you might have no values for specific points. You should then add these points as “zero” or add them as “null” values.
Null values will not be displayed, while “zero” values will be displayed as usual.
The following code adds several points and a null point:
With Series1 do
begin
Clear ;
AddY( 10, ‘John’, clGreen );
AddY( 20, ‘Anne’, clYellow );
AddY( 15, ‘Thomas’, clRed );
AddNull( ‘Peter’ );
AddY( 25, ‘Tony’, clBlue );
AddY( 20, ‘Mike’, clLime );
end;
Each Series type will handle null values in different ways.
Bar, HorizBar, Line, Area and Point do not display null points.
PieSeries use null values as “zero”.
Points can be optionally sorted either by their X values or Y values. The Series.XValues and Series.YValues Order property controls the points Order:
Series1.XValues.Order := loAscending ;
Possible values are: loNone, loAscending or loDescending.
By default, XValues Order is set to loAscending, and YValues Order to loNone, which means new added points are ordered by their X co-ordinate. For non XY Charts, the X co-ordinate is always the point position, starting from zero.
The point Order is used by Series components to draw their points.
Note: Order must be set before points are added to the Series.
You can change the Order property at run-time, followed by a call to Sort method:
Example:
Drop a TChart onto a Form, add a Line Series.
Drop a TButton and assign this code to Button1Click:
Series1.AddArray([ 5, 2, 3, 9]);
Now drop another TButton and add this code to Button2Click:
With Series1 do
begin
YValues.Order:=loAscending;
YValues.Sort;
Repaint;
end;
Now execute and press Button1 to fill Series1, and press Button2 to see Series1 points drawn on Series1 YValues Ascending order, but having the original X co-ordinates.
Note: If you aren’t using X co-ordinates, one more line of code is required.
Drop a new TButton (Button3) and add this code to Button3Click:
Series1.XValues.FillSequence;
Series1.Repaint;
Now points will be “re-numbered”, starting from zero among Series1 XValues axis. This will re-order points so now they will be drawn as if they were originally added to the Series in their new order.
This “two-step” point sorting allows Line Series to draw with vertical orientation.
Adding X co-ordinates to points makes Series components calculate user specific horizontal point positions.
Note: Bar Charts can be difficult to interpret with X co-ordinates.
Pie Series do not allow X co-ordinates.
To add X co-ordinates, simply use the AddXY method:
Drop a TChart, add a Point Series:
With Series1 do
begin
Clear ;
AddXY( 10, 10, ‘Barcelona’, clBlue );
AddXY( 1, 10, ‘San Francisco’, clRed );
end;
Note: If you use a Bubble Series, use the TBubbleSeries AddBubble method.
Remember to set XValues.Order to loNone if don’t want points to be sorted on their X co-ordinate.
Maximum number of points per Series and Series per Chart limited on available memory.
Deleting Points
Simply call the Series.Delete method, passing the point index as the argument. Point index starts at zero.
Series1.Delete( 0 ); { <-- removes the first point in Series1 }
Series1.Delete( Series1.Count - 1 ) ; { <-- removes the last point in Series1 }
An exception “List out of bounds” will be raised when attempting to Delete a non-existing point, so always check there are enough points in the Series prior to delete them:
if Series1.Count > MyIndex then Series1.Delete( MyIndex );
Calling Delete forces re-calculation of Functions and repainting of the Chart.
Retrieving and modifying Points
Once points have been added, you can retrieve their co-ordinates or change them.
The XValues and YValues array properties can be used:
Var MyValue : Double ;
MyValue := Series1.YValues[ 0 ] ; { <-- retrieves the first Y value }
You can traverse these arrays to perform calculations:
Var MyTotal : Double ;
t : Integer ;
MyTotal := 0 ;
for t:= 0 to Series1.Count - 1 do
MyTotal := MyTotal + Series1.YValues[ t ] ;
ShowMessage( FloatToStr( MyTotal ) );
Extended Series types have additional array properties, such as
BubbleSeries RadiusValues. You can access these properties in
the same way as with XValues or YValues arrays:
if BubbleSeries1.RadiusValues[ Index ] > 100 then .....
Modifying point values can be performed using the above properties:
Series1.YValues[ 0 ] := Series1.YValues[ 0 ] + 1 ;
Series1.RefreshSeries ;
The XValues and YValues Locate function searches a specific
value in the List and, if found, returns the value Index, starting
from zero.
Var MyIndex : Integer ;
MyIndex := Series1.YValues.Locate( 123 );
if MyIndex = -1 then
ShowMessage(‘ 123 not found in Series1 !! ‘ )
else
ShowMessage(‘ 123 is the ‘+IntToStr( MyIndex+1 )+’ th point in Series1 !! ‘ );
XValues and YValues properties maintain the following statistical figures:
TotalThe sum of all values in the list.
TotalABSThe sum of all values as absolute (positive).
MaxValueThe maximum value in the list.
MinValueThe minimum value in the list.
You can call manually to RecalcMinMax method to recalculate MinValue and MaxValue. Total and TotalABS are maintained automatically.
These values are used to speed up several Axis scaling calculations and are used as helpers for percent calculations.
TChartValueList object has several other methods and properties to manipulate point values. Please refer to online help documentation.
Whenever points are added, deleted or modified, the Series generates internal notification events. These events are used to recalculate Series that depend on other Series points.
Advanced: You can use RecalcOptions property to control when recalculations are performed.
All Series maintain an internal List of colours. One for each point in the Series.
You can access this list with ValueColor array property, to retrieve or change point colours:
Var MyColor : TColor ;
MyColor := Series1.ValueColor[ 0 ] ;
Series1.ValueColor[ 1 ] := clBlue ;
TeeChart defines a generic colour constant named: clTeeColor.
Points with clTeeColor colour will be drawn using the SeriesColor colour.
Delphi predefines constants for basic colours (clBlue, clRed, etc.). Colours can also be expressed in RGB format. Using a video colour depth of 16k colours or more results in better colour matching.
Each point has an associated text, called XLabel, and declared as a Delphi string.
Point Labels are used in Axis Labels, Chart Legend and Point Marks.
Labels are stored at Series XLabel array property.
You can access and modify XLabel point texts:
Series1.XLabel [ 0 ] := ‘Sales’ ;
Changing the Series type at runtime - Advanced
Every Chart type corresponds to a different Delphi Component.
Changing a Series type involves changing the Series component class.
That means a new Series of the new class must be created, old Series properties should be assigned to the new instance, and finally the old Series must be destroyed.
All this happens automatically when you manually change a Series type at design-time using the Chart Editor Dialog and the Gallery.
You can change a Series type at run-time calling:
ChangeSeriesTypeGallery(Self, MySeries );
Warning:
You should change your private Series components.
You can change also Series components owned by the Form,
but only if not using them after.
Var MySeries : TChartSeries ;
MySeries := Series1 ;
ChangeSeriesTypeGallery(Self, MySeries );