Reputation: 1755
An instance of TChart in Delphi does a nice job of making a graph showing points. This is the "Point" series in the TeeChart gallery.
I would like to draw lines between some, but not all, of the points.
For example, image a scatter diagram of points, which is easy to make with Delphi/TChart. My objective is to draw straight lines between some of the points.
Is this possible?
This code works:
With Chart2.ChartRect do
begin
Canvas.MoveTo(0,0);
Canvas.LineTo(500,500);
end;
The line crosses over the graph, except the line is not visible over the graph. It seems as if the graph much have its own canvas but I can't find any documentation about finding and using it.
So, I need to find the coordinates of some points, as created by TChart, then draw a line between them.
Upvotes: 1
Views: 3120
Reputation: 5039
Some options:
As David Heffernan said, the best option may be to use a series that supports both line segments and pointers. TLineSeries
seems to be the perfect series to do this.
The problem here is that this series draws a line segment between each two consecutive points. You can make a point to be null with setNull(index)
method and this will make the pointer at that index to disappear, but the predecessor and successor line segments will disappear with it.
The easiest solution could be creating a TMyLineSeries inheriting from TLineSeries to override DrawValue method as explained here.
Add a null point after each point you want to be visible. In this option, the only points not followed by a null point would be those where you want a line segment to be drawn.
Add a TLineSeries
per line segment to be drawn.
You always have the possibility to use custom drawing techniques as LU RD said.
Upvotes: 2
Reputation: 34889
To interconnect some points you must follow the drawing principle, all drawing must be done in a paint event.
In TChart, best option here is to do custom drawing in the OnAfterDraw
event.
procedure TForm1.Chart2AfterDraw(Sender: TObject);
begin
With Chart2.ChartRect do
begin
Canvas.MoveTo(0,0);
Canvas.LineTo(500,500);
end;
end;
If you need to know the canvas coordinates for a given point in your array of points.
MyYPosX := Series1.CalcXPos( Series1.XValue[ 0 ] ); { <-- first point }
MyYPosY := Series1.CalcYPos( Series1.YValue[ 0 ] ); { <-- first point }
There is a chapter in the TChart help that is a good introduction to custom drawing: "Custom drawing on the Chart".
From the help:
When to draw ?
The order in which you draw to the Canvas is important.
If you wish Custom drawn items to appear above Chart Series you should use the Chart OnAfterDraw event. The Chart1.OnAfterDraw event is fired each time the Chart component is redrawn, just before copying the internal bitmap to screen.
You can place Custom drawn items above the Chart grid and below the Chart Series by placing your code in the Chart OnBeforeDrawSeries event.
Key Chart Paint events:
- OnBeforeDrawChart
- OnBeforeDrawAxes
- OnBeforeDrawSeries
- OnAfterDraw
Upvotes: 1
Reputation: 612804
Attempting to paint lines yourself is not the way to proceed. The design basis of charting controls is that you define the chart in logical terms and let the control deal with painting it.
So, the way to proceed is to add some line series that represent the lines you wish to be drawn. You can perfectly well add these line series in addition to the other series of your chart.
Regarding your code that attempts to paint on the chart canvas, you should be aware that painting is a delicate process. The design of the system is such that control surfaces are not persistent. Controls are painted in response to the WM_PAINT
message. So, whilst you may be able to paint on a control's canvas as you please, what you paint will survive only until the next cycle. Once the control becomes invalid, it needs to repaint itself. The lesson here is, as a general rule, only to paint in response to WM_PAINT
messages. Or, in OnPaint
events or overridden Paint
methods which are called by the VCL in response to WM_PAINT
.
Upvotes: 1