Recent

Author Topic: primary Questions about TChart  (Read 8827 times)

majid.ebru

  • Sr. Member
  • ****
  • Posts: 494
primary Questions about TChart
« on: February 09, 2018, 07:31:31 pm »
Hi

i have many primary Questions  about TChart.

please help and guide me

how can i fix min and max axis ?

how can i have mult color line?

how can i change value of X axis to Srtinf Text?

how can i show value of point?

« Last Edit: February 09, 2018, 07:35:39 pm by majid.ebru »

majid.ebru

  • Sr. Member
  • ****
  • Posts: 494
Re: primary Questions about TChart
« Reply #1 on: February 09, 2018, 07:32:29 pm »
and

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: primary Questions about TChart
« Reply #2 on: February 09, 2018, 08:08:06 pm »
how can i fix min and max axis ?
Set the Extent of the chart (can be done by code like below, or directly in the Object Inspector)
Code: Pascal  [Select][+][-]
  1.   Chart1.Extent.YMax := 100;
  2.   Chart1.Extent.YMin := 0;
  3.   Chart1.Extent.UseYMax := true;
  4.   Chart1.Extent.UseYMin := true;

how can i change value of X axis to Srtinf Text?
What you probably need is an event handler for the event OnMarkToText of the axis. Example
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Chart1AxisList1MarkToText(var AText: String; AMark: Double);
  2. begin
  3.   if AMark = 0.0 then AText := 'zero';
  4. end;

how can i show value of point?
Set the Marks.Style of the series to smsValue. The settings of Marks.Style define the combinations of the data point parameters (x, y, text) which will be shown as datapoint label (http://wiki.lazarus.freepascal.org/TAChart_documentation#Mark_labels):
Code: Pascal  [Select][+][-]
  1. type
  2.   TSeriesMarksStyle = (
  3.     smsCustom,         { user-defined }
  4.     smsNone,           { no labels }
  5.     smsValue,          { 1234 }
  6.     smsPercent,        { 12 % }
  7.     smsLabel,          { Cars }
  8.     smsLabelPercent,   { Cars 12 % }
  9.     smsLabelValue,     { Cars 1234 }
  10.     smsLegend,         { ? }
  11.     smsPercentTotal,   { 12 % of 1234 }
  12.     smsLabelPercentTotal, { Cars 12 % of 1234 }
  13.     smsXValue);        { 21/6/1996 }    
Change the format string in Marks.Format to limit the number of decimal places, e.g. '%.2f' for 2 decimals only.

I'll have to think about the other questions.
- What does the last image (06.png) mean?
- In image 05.png you have a chart with a line series, and there's a horizontal dividing line. The parts of the line series above the dividing line should be painted in a different color than the parts below the dividing line. Correct? Will be dividing line be fixed, or should it be user-changeable?
« Last Edit: February 09, 2018, 10:14:03 pm by wp »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: primary Questions about TChart
« Reply #3 on: February 09, 2018, 08:16:55 pm »
how can i have mult color line?
There is no reason for multi colour lines. lines are not part of the data only points are the data lines are there to sombolize an idea only it is either negative or positive it can't be both. Don't waste your time on a illogical case.
how can i show value of point?
select the series of the chart and change the marks.style to what ever you need make sure that the marks are visible.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: primary Questions about TChart
« Reply #4 on: February 09, 2018, 09:48:13 pm »
how can i have mult color line?
Drawing the segments of a lineseries in different colors is not supported. But you can use a TUserDrawnSeries instead of the TLineSeries in which you can draw whatever you want - see attached demo.
  • FormCreate defines some dummy data in an array of TDataRec records (record of x and y values) and calculates the range covered by the x and y values (Extent)
  • The Extent has to be passed to the series in its event OnGetBounds.
  • The event OnDraw expects code which paints the entire series. My code simply iterates through the data point array, calculates the image coordinates of each data point (by calling the chart's method GraphToImage) and draws the line segments in the color which is assigned to the current point index in the COLORS array. I should mention that using a Canvas in the OnDraw event is not up to the standard of TAChart which has introduced dedicated drawers. But there's nothing else at the moment, and you hopefully do not want to paint on exotic output devices.
This probably is also the way to answer the question related to image 05.png where the series changes color above and below a dividing line. The only code which has to be added is the calculation of the intersection point of the line segment with the dividing line.
« Last Edit: February 09, 2018, 10:05:39 pm by wp »

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: primary Questions about TChart
« Reply #5 on: February 09, 2018, 10:01:53 pm »
how can i have mult color line?
There is no reason for multi colour lines. lines are not part of the data only points are the data lines are there to sombolize an idea only it is either negative or positive it can't be both. Don't waste your time on a illogical case.
I don't quite understand what you mean, but I could imagine several use cases of multi-colored line segments. For example to highlight segments for which the slope exceeds a given limit. Or - if the series displays a road - the color symbolizes the number of accidents on each segment.
« Last Edit: February 09, 2018, 10:07:30 pm by wp »

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: primary Questions about TChart
« Reply #6 on: February 10, 2018, 09:52:01 pm »
how can i have mult color line?
The TLineSeries of TAChart in Lazarus trunk, r57277, now has a new property "ColorEach" with which you can colorize the line segments individually. The color is added to the data points (4th parameter of the series method AddXY) and can be applied to data points symbol and/or the line segments before or after each data point (TColorEachMode = (ceNone, cePoint, ceLineBefore, ceLineAfter, cePointAndLineBefore, cePointAndLineAfter).

See the demo in the TAChart demo folder (lazarus/components/tachart/demo/line)
« Last Edit: February 10, 2018, 10:57:05 pm by wp »

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: primary Questions about TChart
« Reply #7 on: February 11, 2018, 12:18:42 am »
In the attachment there is a solution to the "color-split" chart. It is based on the user-drawn series as described above. Drag the horizontal dividing line up and down to move the color boundary. There's a little glitch, when data point symbols are shown and the dividing line goes right through the symbol because the symbol is always drawn as a full circle - to get over this a clipping approach should be used.

majid.ebru

  • Sr. Member
  • ****
  • Posts: 494
Re: primary Questions about TChart
« Reply #8 on: February 11, 2018, 07:29:39 am »
In the attachment there is a solution to the "color-split" chart. It is based on the user-drawn series as described above. Drag the horizontal dividing line up and down to move the color boundary. There's a little glitch, when data point symbols are shown and the dividing line goes right through the symbol because the symbol is always drawn as a full circle - to get over this a clipping approach should be used.

Thankyou

your project is very Goooooooood

but i can't compile your project?

waht do i do?

i should update my TChart element?

majid.ebru

  • Sr. Member
  • ****
  • Posts: 494
Re: primary Questions about TChart
« Reply #9 on: February 11, 2018, 07:31:07 am »
how can i have mult color line?
The TLineSeries of TAChart in Lazarus trunk, r57277, now has a new property "ColorEach" with which you can colorize the line segments individually. The color is added to the data points (4th parameter of the series method AddXY) and can be applied to data points symbol and/or the line segments before or after each data point (TColorEachMode = (ceNone, cePoint, ceLineBefore, ceLineAfter, cePointAndLineBefore, cePointAndLineAfter).

See the demo in the TAChart demo folder (lazarus/components/tachart/demo/line)

it's perfect

how can i do that?

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: primary Questions about TChart
« Reply #10 on: February 11, 2018, 10:49:35 am »
In the attachment there is a solution to the "color-split" chart. It is based on the user-drawn series as described above. Drag the horizontal dividing line up and down to move the color boundary. There's a little glitch, when data point symbols are shown and the dividing line goes right through the symbol because the symbol is always drawn as a full circle - to get over this a clipping approach should be used.

Thankyou

your project is very Goooooooood

but i can't compile your project?

waht do i do?

i should update my TChart element?
It seems that you don't use Laz 1.8. You should upgrade, there are many new features.

If you don't want to, just remove the line causing the trouble.

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: primary Questions about TChart
« Reply #11 on: February 11, 2018, 11:48:16 am »
how can i have mult color line?
The TLineSeries of TAChart in Lazarus trunk, r57277, now has a new property "ColorEach" with which you can colorize the line segments individually. The color is added to the data points (4th parameter of the series method AddXY) and can be applied to data points symbol and/or the line segments before or after each data point (TColorEachMode = (ceNone, cePoint, ceLineBefore, ceLineAfter, cePointAndLineBefore, cePointAndLineAfter).

See the demo in the TAChart demo folder (lazarus/components/tachart/demo/line)

it's perfect

how can i do that?
You must install the trunk version of Lazarus (this is the developer version). The easiest way is using the fpcupdeluxe program (https://github.com/newpascal/fpcupdeluxe/releases/tag/v1.6.0n).
« Last Edit: February 11, 2018, 12:12:33 pm by wp »

corpsman

  • New member
  • *
  • Posts: 9
    • My Delphi / Lazarus Programming site ( www.Corpsman.de )
Re: primary Questions about TChart
« Reply #12 on: April 30, 2022, 06:19:05 pm »
In the attachment there is a solution to the "color-split" chart. It is based on the user-drawn series as described above. Drag the horizontal dividing line up and down to move the color boundary. There's a little glitch, when data point symbols are shown and the dividing line goes right through the symbol because the symbol is always drawn as a full circle - to get over this a clipping approach should be used.

The sample is cool but your intersect routine has some errors
here is my version that works better ;)
Code: Pascal  [Select][+][-]
  1. Function Intersect(p1, p2: TPoint; y: Integer): Integer;
  2. Begin
  3.   If p1.y = p2.y Then // fixed catch of div by zero
  4.     Result := (p1.x + p2.x) Div 2
  5.   Else
  6.     Result := round(((p2.x - p1.x) * (y - p1.y)) / (p2.y - p1.y) + p1.x); // reorder to divide "larger" numbers is more stable.
  7. End;  
  8.  

And the Routine that does the rending changed to this:

Code: Pascal  [Select][+][-]
  1.  
  2. Procedure TForm1.Chart1UserDrawnSeries1Draw(ACanvas: TCanvas;
  3.   Const ARect: TRect);
  4.  
  5.   Procedure DrawCircle(p: TPoint; AColor: TColor; R: Integer);
  6.   Begin
  7.     Chart1.Drawer.SetBrushParams(bsSolid, AColor);
  8.     Chart1.Drawer.Ellipse(P.x - R, P.y - R, P.x + R, P.y + R);
  9.   End;
  10.  
  11.   Function GetColor(y, yref: Integer): TColor;
  12.   Begin
  13.     If y > yref Then
  14.       Result := COLOR_BELOW
  15.     Else
  16.       Result := COLOR_ABOVE;
  17.   End;
  18.  
  19. Var
  20.   i: Integer;
  21.   gp: TDoublePoint;
  22.   p1, p2, p3: TPoint;
  23.   yref: Integer;
  24.   x: Integer;
  25.   showDataPoints: Boolean;
  26. Begin
  27.   showDataPoints := Checkbox1.Checked;
  28.   pen.Width := 4;
  29.   Chart1.Drawer.Pen := Pen;
  30.   yref := Chart1.YGraphToImage(Chart1ConstantLine1.Position);
  31.  
  32.   i := 0;
  33.   gp := DoublePoint(Data[i].X, Data[i].Y);
  34.   p1 := Chart1.GraphToImage(gp);
  35.   If showDataPoints Then Begin
  36.     Chart1.Drawer.SetPenParams(psSolid, GetColor(p1.y, yref));
  37.     DrawCircle(p1, GetColor(p1.y, yref), RADIUS); // Fix copy paste index error 2->1
  38.   End;
  39.   For i := 1 To High(Data) Do Begin // draw from second to last point (index of by one correction)
  40.     gp := DoublePoint(Data[i].X, Data[i].Y);
  41.     p2 := Chart1.GraphToImage(gp);
  42.     If (p2.y - yref) * (p1.y - yref) < 0 Then Begin
  43.       p3 := Point(Intersect(p1, p2, yref), yref);
  44.       Chart1.Drawer.SetPenParams(psSolid, GetColor(p1.y, yref), 2);
  45.       Chart1.Drawer.Line(p1, p3);
  46.       Chart1.Drawer.SetPenParams(psSolid, GetColor(p2.y, yref), 2);
  47.       Chart1.Drawer.Line(p3, p2);
  48.     End
  49.     Else Begin
  50.       Chart1.Drawer.SetPenParams(psSolid, GetColor(p2.y, yref), 2);
  51.       Chart1.Drawer.Line(p1, p2);
  52.     End;
  53.     If showDataPoints Then
  54.       DrawCircle(p2, GetColor(p2.y, yref), RADIUS);
  55.     p1 := p2;
  56.   End;
  57. End;
  58.  
  59.  

Thanks a lot for publishing your code.
--
Just try it.

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: primary Questions about TChart
« Reply #13 on: April 30, 2022, 11:07:47 pm »
Thanks for pointing out these bugs. I committed the fix to git-main (except for the reordering of multiplication and division - this really makes no difference with floats).
« Last Edit: May 01, 2022, 11:12:35 am by wp »

Tulurdes

  • Newbie
  • Posts: 3
Re: primary Questions about TChart
« Reply #14 on: February 26, 2024, 06:24:44 pm »
Hi all, I know this topic is a little old but I think it is still very relevant.

I haven't updated from 2.2.4 yet, so I'm not sure if they improved the chart possibilities.
But I've made some changes on this code and made it more compact in the draw event so I could reuse it in a easier way.

I've also added a "fill" option so it could work as both line and area.

But I'm struggling with something, I'd like to make this chart independent, but there are some items that seems impossible to replace since the event only passes as parameters ACanvas and ARect

This are the calls I can't get rid of
Chart1.YGraphToImage (direct access to a chart)
Chart1.GraphToImage (direct access to a chart)
Data.X, Data.Y (direct access to chart data source)

What I want is to be able to create charts at runtime and have this drawing style working on all of them.

Any help would be very welcome.

 

TinyPortal © 2005-2018