TAChart: Add new demo "plotunit" how to create series at runtime.

git-svn-id: trunk@54241 -
This commit is contained in:
wp 2017-02-21 21:55:55 +00:00
parent a597ac1006
commit e113c37338
7 changed files with 550 additions and 0 deletions

6
.gitattributes vendored
View File

@ -4297,6 +4297,12 @@ components/tachart/demo/runtime/chartstyles/project1.lpr svneol=native#text/plai
components/tachart/demo/runtime/chartstyles/readme.txt svneol=native#text/plain
components/tachart/demo/runtime/chartstyles/unit1.lfm svneol=native#text/plain
components/tachart/demo/runtime/chartstyles/unit1.pas svneol=native#text/plain
components/tachart/demo/runtime/plotunit/main.lfm svneol=native#text/plain
components/tachart/demo/runtime/plotunit/main.pas svneol=native#text/plain
components/tachart/demo/runtime/plotunit/plotdemo.lpi svneol=native#text/plain
components/tachart/demo/runtime/plotunit/plotdemo.lpr svneol=native#text/plain
components/tachart/demo/runtime/plotunit/readme.txt svneol=native#text/plain
components/tachart/demo/runtime/plotunit/uplot.pas svneol=native#text/plain
components/tachart/demo/save/main.lfm svneol=native#text/plain
components/tachart/demo/save/main.pas svneol=native#text/plain
components/tachart/demo/save/savedemo.lpi svneol=native#text/plain

View File

@ -0,0 +1,117 @@
object MainForm: TMainForm
Left = 356
Height = 387
Top = 274
Width = 781
Caption = 'MainForm'
ClientHeight = 387
ClientWidth = 781
OnCreate = FormCreate
LCLVersion = '1.7'
object BtnAdd: TButton
AnchorSideLeft.Control = CbPlotTypes
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = Owner
Left = 204
Height = 25
Hint = 'Add selected series type to chart'
Top = 8
Width = 75
BorderSpacing.Left = 8
BorderSpacing.Top = 8
Caption = 'Add'
OnClick = BtnAddClick
TabOrder = 1
end
object Chart: TChart
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = Bevel1
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 4
Height = 335
Top = 44
Width = 773
AxisList = <
item
Minors = <>
Title.LabelFont.Orientation = 900
end
item
Alignment = calBottom
Minors = <>
end>
Foot.Brush.Color = clBtnFace
Foot.Font.Color = clBlue
Title.Brush.Color = clBtnFace
Title.Font.Color = clBlue
Title.Text.Strings = (
'TAChart'
)
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Left = 4
BorderSpacing.Right = 4
BorderSpacing.Bottom = 8
end
object CbPlotTypes: TComboBox
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = BtnAdd
AnchorSideTop.Side = asrCenter
Left = 8
Height = 23
Hint = 'Select series type'
Top = 9
Width = 188
BorderSpacing.Left = 8
BorderSpacing.Top = 8
DropDownCount = 32
ItemHeight = 15
ItemIndex = 1
Items.Strings = (
'Symbols only'
'Symbols + line segments'
'Symbols + cubic spline'
'Symbols + BSpline'
'Symbols + linear fit'
'Symbols + parabolic fit'
'Area'
)
Style = csDropDownList
TabOrder = 0
Text = 'Symbols + line segments'
end
object BtnClear: TButton
AnchorSideLeft.Control = BtnAdd
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = BtnAdd
AnchorSideTop.Side = asrCenter
Left = 287
Height = 25
Hint = 'Clear all series from chart'
Top = 8
Width = 75
BorderSpacing.Left = 8
Caption = 'Clear'
OnClick = BtnClearClick
TabOrder = 2
end
object Bevel1: TBevel
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = BtnAdd
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 8
Height = 3
Top = 41
Width = 765
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 8
BorderSpacing.Top = 8
BorderSpacing.Right = 8
Shape = bsTopLine
end
end

View File

@ -0,0 +1,131 @@
unit main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Types, Forms, Controls,
Graphics, Dialogs, StdCtrls, ExtCtrls,
TAGraph, TACustomSeries, TASeries, TAFuncSeries;
type
{ TMainForm }
TMainForm = class(TForm)
Bevel1: TBevel;
BtnAdd: TButton;
BtnClear: TButton;
Chart: TChart;
CbPlotTypes: TComboBox;
procedure BtnAddClick(Sender: TObject);
procedure BtnClearClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
public
end;
var
MainForm: TMainForm;
implementation
{$R *.lfm}
uses
TATypes, uplot;
const
PALETTE: array[0..7] of TColor = (
clRed, clGreen, clBlue, clOlive, clFuchsia, clAqua, clBlack, clLime);
SYMBOLS: array[0..5] of TSeriesPointerStyle = (
psCircle, psRectangle, psTriangle, psDiamond, psDownTriangle, psFullStar);
LINESTYLES: array[0..4] of TPenStyle = (
psSolid, psDot, psDash, psDashDot, psDashDotDot);
{ TMainForm }
procedure CreateData(ACount: Integer; var x, y: TDoubleDynArray);
const
MIN = -10;
MAX = 10;
var
i: Integer;
begin
SetLength(x, ACount);
SetLength(y, ACount);
for i:=0 to ACount-1 do
begin
x[i] := MIN + (MAX - MIN) * i / (ACount - 1);
y[i] := random;
end;
end;
procedure TMainForm.BtnAddClick(Sender: TObject);
var
x, y: TDoubleDynArray;
colorIndex: Integer;
symbolIndex: Integer;
linestyleIndex: Integer;
plottype: Integer;
begin
if Chart.SeriesCount = 0 then
PrepareChart(Chart, 'x axis', 'y axis', 'TAChart Plot Demo', 'Written by Lazarus');
CreateData(Random(20)+3, x, y);
colorIndex := Chart.SeriesCount mod Length(PALETTE);
symbolIndex := Chart.SeriesCount mod Length(SYMBOLS);
lineStyleIndex := Chart.SeriesCount mod Length(LINESTYLES);
plottype := PtrInt(CbPlotTypes.Items.Objects[CbPlotTypes.ItemIndex]);
Plot(Chart,
x, y,
'Series #'+IntToStr(Chart.SeriesCount+1),
PALETTE[colorIndex],
SYMBOLS[symbolIndex],
LINESTYLES[linestyleIndex],
TPlotType(abs(plottype)),
plottype < 0 // with symbols if value is negative
);
end;
procedure TMainForm.BtnClearClick(Sender: TObject);
begin
Chart.ClearSeries;
Chart.Legend.Visible := false;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
Chart.Visible := false;
CbPlotTypes.Items.Clear;
// Encode plot types into the object of the CbPlotTypes combobox:
// - The ord value of the plot type is cast to an object if the series is
// without symbols.
// - The negative ord value of the plot type is cast if an object if the
// series is with symbols.
CbPlotTypes.Items.AddObject('Symbols only', TObject(PtrInt(ptSymbolsOnly)));
CbPlotTypes.Items.AddObject('Line segments w/ symbols', TObject(-PtrInt(ptSegments)));
CbPlotTypes.Items.AddObject('Line segments w/o symbols', TObject(PtrInt(ptSegments)));
CbPlotTypes.Items.AddObject('Cubic spline w/ symbols', TObject(-PtrInt(ptCubicSpline)));
CbPlotTypes.Items.AddObject('Cubic spline w/o symbols', TObject(PtrInt(ptCubicSpline)));
CbPlotTypes.Items.AddObject('B-Spline w/ symbols', TObject(-PtrInt(ptBSpline)));
CbPlotTypes.Items.AddObject('B-Spline w/o symbols', TObject(PtrInt(ptBSpline)));
CbPlotTypes.Items.AddObject('Linear fit w/ symbols', TObject(-PtrInt(ptLinearfit)));
CbPlotTypes.Items.AddObject('Linear fit w/o symbols', TObject(PtrInt(ptLinearFit)));
CbPlotTypes.Items.AddObject('Parabolic fit w/symbols', TObject(-PtrInt(ptSquareFit)));
CbPlotTypes.Items.AddObject('Parabolic fit w/o symbols)', TObject(PtrInt(ptSquareFit)));
CbPlotTypes.Items.AddObject('Area (no symbols)', TObject(PtrInt(ptArea)));
CbPlotTypes.Items.AddObject('Bars (horizontal)', TObject(PtrInt(ptBars)));
CbPlotTypes.Items.AddObject('Columns (vertical)', TObject(PtrInt(ptColumns)));
CbPlotTypes.ItemIndex := 1;
end;
end.

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="10"/>
<PathDelim Value="\"/>
<General>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="plotdemo"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="TAChartLazarusPkg"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="3">
<Unit0>
<Filename Value="plotdemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="MainForm"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit1>
<Unit2>
<Filename Value="uplot.pas"/>
<IsPartOfProject Value="True"/>
</Unit2>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="plotdemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<UseExternalDbgSyms Value="True"/>
</Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,21 @@
program plotdemo;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, main, tachartlazaruspkg, uplot
{ you can add units after this };
{$R *.res}
begin
RequireDerivedFormResource:=True;
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

View File

@ -0,0 +1,7 @@
The demo "plotunit" show how to generate a series and insert it into a chart
at runtime. The main series types of TAChart are supported.
The main plotting routines are in unit "uplot.pas":
- PrepareChart: Sets up chart title, footer and axis labels
- Plot: Takes a variety of parameters to plot the data array x vs y.

View File

@ -0,0 +1,180 @@
unit uplot;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Graphics, types,
TAGraph, TATypes, TACustomSeries;
type
TPlotType = (ptSymbolsOnly, ptSegments, ptCubicSpline, ptBSpline,
ptLinearFit, ptSquareFit, ptArea, ptColumns, ptBars);
procedure PrepareChart(AChart: TChart;
xTitle, yTitle, AChartTitle, AChartFooter: String);
function Plot(AChart: TChart; x,y: TDoubleDynArray; ALegendText: String;
AColor: TColor; ASymbol: TSeriesPointerStyle; ALineStyle: TPenStyle;
APlotType: TPlotType; AShowSymbols: Boolean = false): TChartSeries;
implementation
uses
Math, LCLIntf,
TAFitUtils, TASeries, TAFuncSeries, TATools;
procedure PrepareChart(AChart: TChart;
xTitle, yTitle, AChartTitle, AChartFooter: String);
begin
AChart.BottomAxis.Title.Visible := xTitle <> '';
AChart.BottomAxis.Title.Caption := xTitle;
AChart.BottomAxis.Title.LabelFont.Style := [fsBold];
AChart.BottomAxis.Title.LabelFont.Size := 10;
AChart.BottomAxis.Grid.Color := $E0E0E0;
AChart.BottomAxis.Grid.Style := psSolid;
AChart.BottomAxis.AxisPen.Visible := true;
AChart.LeftAxis.Title.Visible := yTitle <> '';
AChart.LeftAxis.Title.Caption := yTitle;
AChart.LeftAxis.Title.LabelFont.Style := [fsBold];
AChart.LeftAxis.Title.LabelFont.Size := 10;
AChart.LeftAxis.Grid.Color := $E0E0E0;
AChart.LeftAxis.Grid.Style := psSolid;
AChart.LeftAxis.AxisPen.Visible := true;
AChart.Title.Visible := AChartTitle <> '';
AChart.Title.Text.Text := AChartTitle;
AChart.Title.Font.Style := [fsBold];
AChart.Title.Font.Size := 14;
AChart.Foot.Visible := AChartFooter <> '';
AChart.Foot.Text.Text := AChartFooter;
AChart.Foot.Font.Size := 8;
AChart.Foot.Alignment := taLeftJustify;
AChart.Legend.SymbolWidth := 40;
AChart.Legend.Frame.Color := clSilver;
AChart.Backcolor := clWhite;
AChart.Frame.Color := clSilver;
AChart.Visible := True;
end;
function Plot(AChart: TChart; x,y: TDoubleDynArray; ALegendText: String;
AColor: TColor; ASymbol: TSeriesPointerStyle; ALineStyle: TPenStyle;
APlotType: TPlotType; AShowSymbols: Boolean = false): TChartSeries;
var
i: Integer;
begin
case APlotType of
ptSymbolsOnly, ptSegments:
begin
Result := TLineSeries.Create(AChart.Owner);
with TLineSeries(Result) do
begin
ShowPoints := (APlotType = ptSymbolsOnly) or AShowSymbols;
ShowLines := (APlotType <> ptSymbolsOnly);
LinePen.Style := ALineStyle;
SeriesColor := AColor;
Pointer.Brush.Color := AColor;
Pointer.Pen.Color := AColor;
Pointer.Style := ASymbol;
end;
end;
ptCubicSpline:
begin
Result := TCubicSplineSeries.create(AChart.Owner);
with TCubicSplineSeries(Result) do
begin
Pen.Color := AColor;
Pen.Style := ALineStyle;
Pointer.Brush.Color := AColor;
Pointer.Pen.Color := AColor;
Pointer.Style := ASymbol;
Pointer.Visible := AShowSymbols;
end;
end;
ptBSpline:
begin
Result := TBSplineSeries.Create(AChart.Owner);
with TBSplineSeries(Result) do
begin
Pen.Color := AColor;
Pen.Style := ALineStyle;
Pointer.Brush.Color := AColor;
Pointer.Pen.Color := AColor;
Pointer.Style := ASymbol;
Pointer.Visible := AShowSymbols;
end;
end;
ptLinearFit, ptSquareFit:
begin
Result := TFitSeries.Create(AChart.Owner);
with TFitSeries(Result) do
begin
Pen.Color := AColor;
Pen.Style := ALineStyle;
if APlotType = ptLinearfit then
begin
FitEquation := feLinear;
Title := 'linear fit to ' + ALegendText;
end else
begin
FitEquation := fePolynomial;
ParamCount := 3; // parabolic fit needs 3 parameters
Title := 'parabolic fit to ' + ALegendText;
end;
Pointer.Brush.Color := AColor;
Pointer.Pen.Color := AColor;
Pointer.Style := ASymbol;
Pointer.Visible := AShowSymbols;
end;
end;
ptArea:
begin
Result := TAreaSeries.Create(AChart.Owner);
with TAreaSeries(Result) do
begin
SeriesColor := AColor;
AreaContourPen.Color := AColor;
AreaLinesPen.Color := AColor;
end;
end;
ptColumns, ptBars:
begin
Result := TBarSeries.Create(AChart.Owner);
with TBarSeries(Result) do
begin
BarBrush.Color := AColor;
BarPen.Color := AColor;
BarWidthStyle := bwPercentMin;
if APlotType = ptBars then begin
AxisIndexX := AChart.LeftAxis.Index;
AxisIndexY := AChart.BottomAxis.Index;
end else begin
AxisIndexX := AChart.BottomAxis.Index;
AxisIndexY := AChart.LeftAxis.Index;
end;
end;
end;
end;
Result.Title := ALegendText;
if Result is TBasicPointSeries then
with TBasicPointSeries(Result) do
for i:=0 to Min(High(x), High(y)) do
AddXY(x[i], y[i]);
AChart.AddSeries(Result);
AChart.Legend.Visible := AChart.SeriesCount > 1;
// Paint new series in front of the others
Result.ZPosition := AChart.SeriesCount;
end;
end.