Sign in Join
Wiki copytemporary

TAChart Tutorial: Multiple Panes in one Chart: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Introduction
22
33This tutorial shows how to create a chart with multiple series in their own panes and with their own left axes and one common bottom axis. It was created while checking out the nice "Panes demo" which you can find in the folder `components/tachart/demo/panes` of your Lazarus installation. Since a second topic is included in this sample project it may be a bit difficult to catch the basic idea. So here we explain how you can do this from scratch.
44
55The setup of charts, axes, series and panes in TAChart is not done from a single dialog window. Instead you add components and change their settings in the object inspector to get the wanted behaviour.
66
77Three types of components will be needed for the demo:
88
99- TChart
1010- TChartAxisTransformation, and
1111- TRandomChartSource.
1212
1313At designtime a series is added to the chart using the Series Editor. The chart component has a property called `AxisList` where additional axes can be added. This one is important.
1414
1515So lets start!
1616
1717## Step by step
1818
1919### Add chart and series
2020
2121Start a new project and save it. Drop a `TChart` on the main form and align it to client. Right-click the chart to access the Series Editor. Add three LineSeries from the Series Editor. Set the `SeriesColor` of the three series to `clRed`, `clBlue`, and `clLime`, respectively.
2222
2323### Add random data to the series
2424
2525Add three `TRandomChartSource` components to the form and set their values using the Object Inspector:
2626
2727- `PointsNumber` 100 (100 random values will be added to the linked series. )
2828- `XMax` 50 (For the bottom axis)
2929- `XMin` 0 (For the bottom axis)
3030- `YCount` 1
3131- `YMax` 50 (For left axes)
3232- `YMin` 0 (For left axes)
3333
3434Then proceed with:
3535
3636- Go to `Chart1LineSeries1` "Source" property and set it to `RandomChartSource1`
3737- Go to `Chart1LineSeries2` "Source" property and set it to `RandomChartSource2`
3838- Go to `Chart1LineSeries3` "Source" property and set it to `RandomChartSource3`
3939
4040Now you will have visible graphs on the charts. But the chart is very crowded because all series still share the same axis.
4141
4242### Add more axes
4343
4444Now we are going to create the separate axes. Click the chart, go to the Object Inspector and find the charts AxisList property. Bring up the AxisList Editor and add two more axes of the "Left axis" type. The new axes will have the indices 2 and 3. (The old, original y axis has the index 0 and the x axis has index 1).
4545
4646### Link series to axes
4747
4848Go to the Series Editor again and:
4949
5050- For `Chart1LineSeries1` set the property `AxisIndexY` to 0
5151- For `LineSeries2` set the property `AxisIndexY` to 2
5252- For `LineSeries3` set the property `AxisIndexY` to 3
5353
5454### Group the axes
5555
5656An axis has a property named `Group`. By setting all left axes to the same group, the values are put together in a vertical line. For each Left Axis in this example, set the Group property to 1 and leave the Bottom Axis at 0.
5757
5858### Set the axis range
5959
6060Go to the AxisList property of the Chart and bring up the AxisList Editor. Edit the `Marks.Range` of each y axis so that they look like this:
6161
6262- `Marks.Range.Max`: 50
6363- `Marks.Range.Min`: 0
6464- `Marks.Range.UseMax`: True
6565- `Marks.Range.UseMin`: True
6666
6767This step separates the axis labels of each pane. Otherwise, the labels of one pane would overlap those from the other panes.
6868
6969(Accordingly, you can also set the `Range` properties of each y axis (without the "Marks"!) in order to achieve a consistent scaling of the three axes).
7070
7171### Use chart axis transformations
7272
7373In order to split the three series into separate panes we need to transform the axis coordinate system such that each axis is drawn only in its own region. This is done by means of [[TAChart documentation|ChartAxisTransformations]].
7474
7575TAChart employs three coordinate systems in the transition from "real world" data to the pixels on the screen:
7676
7777- [[TAChart documentation|Axis coordinates]] are the coordinates in which the data come in, or, in other words, which are labeled along the axes. In our project, these are numbers ranging between 0 and 50 as setup for the RandomChartSources.
7878- [[TAChart documentation|Graph coordinates]] are obtained after applying transformations. For our particular purpose there is an [[TAChart documentation|AutoScaleAxisTransform]] which maps the data range of the "real world" data onto a given graph coordinate range of the axis.
7979- [[TAChart documentation|Image coordinates]] belong to the pixels on the screen calculated from the graph coordinates.
8080
8181We can setup the graph coordinates in any convenient way. Suppose, the graph coordinates range from 0 to 6 (we could use any other numbers, but these are easy to calculate with). Then we can have the effect of three separate panes by assigning the first y axis to the lower third, the second y axis to the middle third, and the third y axis to the upper third of the entire range. Therefore, the first series will be plotted in the lower third of the chart since it is linked to the first y axis, etc.
8282
8383In practice, add three `ChartAxisTransformations` to the form. Double-click on each (or find the property `List` in the Object Inspector of the `ChartAxisTransform`) and bring up the "Axis Transformations Editor". Click "Add" to create a Transformation and choose "Autoscale"). This adds an `AutoScaleAxisTransform` to each `ChartAxisTransformations` component. Select each `AutoScaleAxisTransform` and enter the following numbers for the properties `MaxValue` and `MinValue` which define the range for the axis transform:
8484
8585`ChartAxisTransformations1AutoScaleAxisTransform1`: `MaxValue` 1.85 and `MinValue` 0.15 `ChartAxisTransformations1AutoScaleAxisTransform2`: `MaxValue` 3.85 and `MinValue` 2.15 `ChartAxisTransformations1AutoScaleAxisTransform3`: `MaxValue` 5.85 and `MinValue` 4.15
8686
8787Note that these numbers are offset by 0.15 from the thirds discussed above (0 to 2, 2 to 4, and 4 to 6). This produces a little gap between the panes and makes the chart more pleasant.
8888
8989The entire mapping procedure is sketched in the next diagram:
9090
9191![](/wiki-images/3/37/MappingToPanes.png)
9292
9393Bring up the Object Inspector for the chart, choose the `AxisList` property to get the AxisList Editor and connect each left axis to the corresponding transformation. This is done by editing the "transformations" property of each y axis:
9494
9595- 0 - Left: `Transformations = 'ChartAxisTransformations1'`
9696- 2 - Left: `Transformations = 'ChartAxisTransformations2'`
9797- 3 - Left: `Transformations = 'ChartAxisTransformations3'`
9898
9999To get the correct spacing at the top and at the bottom of the chart we must let the y axis extends match our chosen graph coordinates range of 0 to 6. Go to the Chart properties and edit the these extent settings:
100100
101101- `Extent.YMax`: 6
102102- `Extent.YMin`: 0
103103- `Extent.UseYMax`: true
104104- `Extent.UseYMin`: true
105105
106106### Adding axis titles
107107
108108Finally we add titles to the axis. In the Object Inspector set the following properties of each axis:
109109
110110- 0 - Left: `Title.Caption = 'bottom y axis'`
111111- 1 - Bottom: `Title.Caption = 'x axis'`
112112- 2 - Left: `Title.Caption = 'center y axis'`
113113- 3 - Left: `Title.Caption = 'top y axis'`
114114
115115Set the property `Visible` of each axis title to true to show the titles. However, you'll notice two issues:
116116
1171171. The titles of the manually created y axes are not rotated by 90 degress. To fix this, go to the `Font.Orientation` property of the `Title` properties of these axes and enter the value `900`. This is the rotation angle in tenths of degrees.
1181182. All y axes are drawn in the center of the vertical chart extent and, therefore, overlap. It would be better if each title would be drawn within the range of the corresponding axis. To fix this set the property `PositionOnMarks` of the `Title` of each axis to true.
119119
120120## Result
121121
122122Now your application should look like this:
123123
124124![](/wiki-images/3/3f/MultiPanes.png)
125125
126126## Source code
127127
128128### Project file
129129
130130``` pascal
131131program panes_demo;
132132
133133{$mode objfpc}{$H+}
134134
135135uses
136136 {$IFDEF UNIX}{$IFDEF UseCThreads}
137137 cthreads,
138138 {$ENDIF}{$ENDIF}
139139 Interfaces, // this includes the LCL widgetset
140140 Forms, Unit1, tachartlazaruspkg
141141 { you can add units after this };
142142
143143{$R *.res}
144144
145145begin
146146 Application.Title := 'TAChart panes demo';
147147 RequireDerivedFormResource := True;
148148 Application.Initialize;
149149 Application.CreateForm(TForm1, Form1);
150150 Application.Run;
151151end.
152152```
153153
154154### Unit1.pas
155155
156156``` pascal
157157unit Unit1;
158158
159159{$mode objfpc}{$H+}
160160
161161interface
162162
163163uses
164164 Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
165165 TAGraph, TASeries, TASources, TATransformations;
166166
167167type
168168
169169 { TForm1 }
170170
171171 TForm1 = class(TForm)
172172 Chart1: TChart;
173173 Chart1LineSeries1: TLineSeries;
174174 Chart1LineSeries2: TLineSeries;
175175 Chart1LineSeries3: TLineSeries;
176176 ChartAxisTransformations1: TChartAxisTransformations;
177177 ChartAxisTransformations1AutoScaleAxisTransform1: TAutoScaleAxisTransform;
178178 ChartAxisTransformations2: TChartAxisTransformations;
179179 ChartAxisTransformations2AutoScaleAxisTransform1: TAutoScaleAxisTransform;
180180 ChartAxisTransformations3: TChartAxisTransformations;
181181 ChartAxisTransformations3AutoScaleAxisTransform1: TAutoScaleAxisTransform;
182182 RandomChartSource1: TRandomChartSource;
183183 RandomChartSource2: TRandomChartSource;
184184 RandomChartSource3: TRandomChartSource;
185185 end;
186186
187187var
188188 Form1: TForm1;
189189
190190implementation
191191
192192{$R *.lfm}
193193
194194end.
195195```
196196
197197### Unit1.lfm
198198
199-``` pascal
199+``` lfm
200200object Form1: TForm1
201201 Left = 425
202202 Height = 454
203203 Top = 249
204204 Width = 616
205205 Caption = 'Form1'
206206 ClientHeight = 454
207207 ClientWidth = 616
208208 LCLVersion = '1.1'
209209 object Chart1: TChart
210210 Left = 0
211211 Height = 454
212212 Top = 0
213213 Width = 616
214214 AxisList = <
215215 item
216216 Group = 1
217217 Marks.Range.Max = 50
218218 Marks.Range.UseMax = True
219219 Marks.Range.UseMin = True
220220 Minors = <>
221221 Range.Max = 50
222222 Range.UseMax = True
223223 Range.UseMin = True
224224 Title.LabelFont.Orientation = 900
225225 Title.Visible = True
226226 Title.Caption = 'bottom y axis'
227227 Title.PositionOnMarks = True
228228 Transformations = ChartAxisTransformations1
229229 end
230230 item
231231 Alignment = calBottom
232232 Minors = <>
233233 Title.Visible = True
234234 Title.Caption = 'x axis'
235235 end
236236 item
237237 Group = 1
238238 Marks.Range.Max = 50
239239 Marks.Range.UseMax = True
240240 Marks.Range.UseMin = True
241241 Minors = <>
242242 Range.Max = 50
243243 Range.UseMax = True
244244 Range.UseMin = True
245245 Title.LabelFont.Orientation = 900
246246 Title.Visible = True
247247 Title.Caption = 'center y axis'
248248 Title.PositionOnMarks = True
249249 Transformations = ChartAxisTransformations2
250250 end
251251 item
252252 Group = 1
253253 Marks.Range.Max = 50
254254 Marks.Range.UseMax = True
255255 Marks.Range.UseMin = True
256256 Minors = <>
257257 Range.Max = 50
258258 Range.UseMax = True
259259 Range.UseMin = True
260260 Title.Margins.Bottom = 4
261261 Title.LabelFont.Orientation = 900
262262 Title.Visible = True
263263 Title.Caption = 'top y axis'
264264 Title.PositionOnMarks = True
265265 Transformations = ChartAxisTransformations3
266266 end>
267267 Extent.UseYMax = True
268268 Extent.UseYMin = True
269269 Extent.YMax = 6
270270 Foot.Brush.Color = clBtnFace
271271 Foot.Font.Color = clBlue
272272 Title.Brush.Color = clBtnFace
273273 Title.Font.Color = clBlue
274274 Title.Text.Strings = (
275275 'TAChart'
276276 )
277277 Align = alClient
278278 ParentColor = False
279279 object Chart1LineSeries1: TLineSeries
280280 AxisIndexY = 0
281281 LinePen.Color = clRed
282282 Source = RandomChartSource1
283283 end
284284 object Chart1LineSeries2: TLineSeries
285285 AxisIndexY = 2
286286 LinePen.Color = clBlue
287287 Source = RandomChartSource2
288288 end
289289 object Chart1LineSeries3: TLineSeries
290290 AxisIndexY = 3
291291 LinePen.Color = clLime
292292 Source = RandomChartSource3
293293 end
294294 end
295295 object RandomChartSource1: TRandomChartSource
296296 PointsNumber = 100
297297 RandSeed = 1497444274
298298 XMax = 50
299299 XMin = 0
300300 YMax = 50
301301 YMin = 0
302302 left = 122
303303 top = 46
304304 end
305305 object RandomChartSource2: TRandomChartSource
306306 PointsNumber = 100
307307 RandSeed = 1497485782
308308 XMax = 50
309309 XMin = 0
310310 YMax = 50
311311 YMin = 0
312312 left = 123
313313 top = 123
314314 end
315315 object RandomChartSource3: TRandomChartSource
316316 PointsNumber = 100
317317 RandSeed = 1497547025
318318 XMax = 50
319319 XMin = 0
320320 YMax = 50
321321 YMin = 0
322322 left = 122
323323 top = 208
324324 end
325325 object ChartAxisTransformations1: TChartAxisTransformations
326326 left = 369
327327 top = 46
328328 object ChartAxisTransformations1AutoScaleAxisTransform1: TAutoScaleAxisTransform
329329 MaxValue = 1.85
330330 MinValue = 0.15
331331 end
332332 end
333333 object ChartAxisTransformations2: TChartAxisTransformations
334334 left = 370
335335 top = 123
336336 object ChartAxisTransformations2AutoScaleAxisTransform1: TAutoScaleAxisTransform
337337 MaxValue = 3.85
338338 MinValue = 2.15
339339 end
340340 end
341341 object ChartAxisTransformations3: TChartAxisTransformations
342342 left = 365
343343 top = 208
344344 object ChartAxisTransformations3AutoScaleAxisTransform1: TAutoScaleAxisTransform
345345 MaxValue = 5.85
346346 MinValue = 4.15
347347 end
348348 end
349349end
350350```
351351
352352---
353353*From the Free Pascal wiki, page "TAChart Tutorial: Multiple Panes in one Chart", as it stood on 2022-09-06 after a change by Andries, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
354354Category: Components
355355Category: Graphics
356356Category: Lazarus
357357Category: TAChart
358358Category: Tutorials

Back to history