Reputation: 163
I need to add chartseries during runtime cause I don't know how many chart series I'll have at design time, so I wrote some code to add it. However for some reason it's not working...
Most of my charts require only 1 chartseries, except 1 which requires 2. So I could add an extra form with 2 chartseries on, but that would clash my design for this particular form to be generic in what kind of data it can display. So right now, I have 1 chartseries during design time + 1 extra during runtime. The chartseries added in design mode works perfectly. The one I added during runtime is pretty much an exact copy of the properties of the chart in the form file (.dfm).
Form behind:
object frmChartTest: TfrmChartTest
Left = 0
Top = 0
Caption = 'Test'
ClientHeight = 299
ClientWidth = 635
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object chtTestChart: TDBChart
Left = 0
Top = 0
Width = 635
Height = 299
Title.Text.Strings = (
'Title Chart')
BottomAxis.DateTimeFormat = 'dd/MM/yyyy'
BottomAxis.Increment = 1.000000000000000000
BottomAxis.LabelStyle = talValue
BottomAxis.Title.Caption = 'Title bottom axe'
LeftAxis.Automatic = False
LeftAxis.AutomaticMaximum = False
LeftAxis.AutomaticMinimum = False
LeftAxis.ExactDateTime = False
LeftAxis.Maximum = 100.000000000000000000
LeftAxis.Title.Caption = 'Title Y-ax'
Legend.Visible = False
View3D = False
View3DOptions.Elevation = 344
Zoom.Pen.Mode = pmNotXor
Align = alClient
BevelOuter = bvNone
Color = clWhite
TabOrder = 0
DefaultCanvas = 'TGDIPlusCanvas'
ColorPaletteIndex = 13
end
end
actual code:
unit ChartTest;
interface
uses
Data.DB, FireDAC.Comp.Client, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.DateUtils,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VclTee.TeeGDIPlus, VclTee.TeEngine, Vcl.ExtCtrls, VclTee.TeeProcs,
VclTee.Chart, VclTee.DBChart;
type
TfrmChartTest = class(TForm)
chtTestChart: TDBChart;
procedure FormShow(Sender: TObject);
private
procedure CreateField(MemoryDataSet: TFDMemTable; AFieldName: string; AFieldType: TFieldType; ASize: integer);
procedure AddValues(FieldNameXAxe, FieldNameYAxe: string; LineColor: TColor);
function GetData(): TFDMemTable;
end;
var
frmChartTest: TfrmChartTest;
implementation
{$R *.dfm}
const
dateField: string = 'date1';
intField1: string = 'int1';
intField2: string = 'int2';
{ TfrmChartTest }
procedure TfrmChartTest.AddValues(FieldNameXAxe, FieldNameYAxe: string;
LineColor: TColor);
var
chartSeries: TChartSeries;
begin
chartSeries := TChartSeries.Create(chtTestChart);
with chartSeries do begin
ParentChart := chtTestChart;
Marks.Style := smsXValue;
DataSource := GetData();
SeriesColor := LineColor;
XLabelsSource := FieldNameXAxe;
Pen.Color := LineColor;
Pen.Width := 3;
XValues.DateTime := True;
XValues.Name := 'X';
XValues.Order := loAscending;
XValues.ValueSource := FieldNameXAxe;
YValues.Name := 'Y';
YValues.Order := loNone;
YValues.ValueSource := FieldNameYAxe;
DrawBetweenPoints := True;
end;
chtTestChart.AddSeries(chartSeries);
chartSeries.Active := True;
end;
procedure TfrmChartTest.CreateField(MemoryDataSet: TFDMemTable;
AFieldName: string; AFieldType: TFieldType; ASize: integer);
begin
with MemoryDataSet.FieldDefs.AddFieldDef do begin
name := AFieldName;
DataType := AFieldType;
if ASize > 0 then begin
Size := ASize;
end;
end;
end;
procedure TfrmChartTest.FormShow(Sender: TObject);
begin
AddValues(dateField, intField1, clRed);
AddValues(dateField, intField2, clBlue);
chtTestChart.LeftAxis.Minimum := 45;
chtTestChart.LeftAxis.Maximum := 175;
end;
function TfrmChartTest.GetData: TFDMemTable;
var
Data: TFDMemTable;
begin
Data := TFDMemTable.Create(nil);
CreateField(Data, dateField, ftDate, 0);
CreateField(Data, intField1, ftInteger, 0);
CreateField(Data, intField2, ftInteger, 0);
Data.CreateDataSet();
Data.Append();
Data.FieldByName(dateField).AsDateTime := Yesterday;
Data.FieldByName(intField1).AsInteger := 50;
Data.FieldByName(intField2).AsInteger := 130;
Data.Append();
Data.FieldByName(dateField).AsDateTime := Today;
Data.FieldByName(intField1).AsInteger := 70;
Data.FieldByName(intField2).AsInteger := 150;
Data.Append();
Data.FieldByName(dateField).AsDateTime := Tomorrow;
Data.FieldByName(intField1).AsInteger := 90;
Data.FieldByName(intField2).AsInteger := 170;
Exit(Data);
end;
end.
No values from the Y-axe are displayed. Values on X-axe are displayed. No error messages are shown, it's just not working as intended.
Upvotes: 1
Views: 1735
Reputation: 3830
The only functional problem with your code is that you create an instance of abstract TChartSeries
. You didn't mention what kind of series are you trying to create at run-time. To fix this just pick a specific series like TLineSeries
or TBarSeries
and your code should work.
Besides that the way you create series at runtime is a bit awkward. You don't need to call AddSeries
after you set property ParentChart
of series. Those two are basically equivalent. The simplest way to create parented series is described in the documentation and it can be a one-liner (this one creates bar series):
chartSeries := chtTestChart.AddSeries(TBarSeries.Create(Self));
{ setup series here }
You also don't need to set property Active
of series to True
, because it's the default value.
Upvotes: 2