Scope of TChart.Assign method
Scope of TChart.Assign method
Hi,
The TChart.Assign method seems not to copy series attributes, such as colour and title. To copy series attributes, I have to use separate TChartSeries.Assign calls.
But I don't have to do this with TChartAxis. The TChart.Assign method copies axis attributes but not series attributes.
Is this the expected behaviour?
Thanks
Toreba
The TChart.Assign method seems not to copy series attributes, such as colour and title. To copy series attributes, I have to use separate TChartSeries.Assign calls.
But I don't have to do this with TChartAxis. The TChart.Assign method copies axis attributes but not series attributes.
Is this the expected behaviour?
Thanks
Toreba
Re: Scope of TChart.Assign method
Hello Toreba,
Note the assign methods assign the values of the properties form the source to the target. Since the series are objects that at the same time store a reference to their parent chart, changing that would remove the series from the original chart.
I'd suggest you to use the CloneChart series after assigning or cloning the chart. Ie:
Note the assign methods assign the values of the properties form the source to the target. Since the series are objects that at the same time store a reference to their parent chart, changing that would remove the series from the original chart.
I'd suggest you to use the CloneChart series after assigning or cloning the chart. Ie:
Code: Select all
CloneChartSeries(Series1, Chart2);
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
Re: Scope of TChart.Assign method
Yeray,
Ah yes, I see what you mean.
In fact, what I'm trying to do is allow a user to reset all display attributes of a chart by picking a template, i.e. a saved graph with no data, previously streamed to a database BLOB field using SaveChartToStream. But once the saved chart is retrieved, there doesn't seem to be a combination of available methods that allows me to code a function that updates display attributes from the saved graph, while leaving the chart series values untouched. In the end I have to rebuild all the series value lists from their data sources, which is a lot slower than merely updating their display attributes.
Or am I missing something that would help?
Regards
Toreba
Ah yes, I see what you mean.
In fact, what I'm trying to do is allow a user to reset all display attributes of a chart by picking a template, i.e. a saved graph with no data, previously streamed to a database BLOB field using SaveChartToStream. But once the saved chart is retrieved, there doesn't seem to be a combination of available methods that allows me to code a function that updates display attributes from the saved graph, while leaving the chart series values untouched. In the end I have to rebuild all the series value lists from their data sources, which is a lot slower than merely updating their display attributes.
Or am I missing something that would help?
Regards
Toreba
Re: Scope of TChart.Assign method
Hello Toreba,
I've done a simple example doing what I understand you are trying to achieve.
- Chart1 has some settings modified (I apply a theme to it). It also has a series with some values.
- Chart2 has another series with other data loaded.
- Button1 exports Chart1 to a memory stream (without the data), loads the chart to a tmpChart and then applies the formatting to Chart2. So Chart2 now looks as Chart1, using a stream and without moving any series or data.
I've done a simple example doing what I understand you are trying to achieve.
- Chart1 has some settings modified (I apply a theme to it). It also has a series with some values.
- Chart2 has another series with other data loaded.
- Button1 exports Chart1 to a memory stream (without the data), loads the chart to a tmpChart and then applies the formatting to Chart2. So Chart2 now looks as Chart1, using a stream and without moving any series or data.
Code: Select all
uses Series, TeeThemes, TeeStore;
procedure TForm1.FormCreate(Sender: TObject);
begin
with Chart1.AddSeries(TBarSeries) as TBarSeries do
begin
ColorEachPoint:=true;
FillSampleValues();
end;
ApplyChartTheme(TAndrosTheme, Chart1);
with Chart2.AddSeries(TPieSeries) as TPieSeries do
begin
FillSampleValues();
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var tmpStream: TMemoryStream;
tmpChart: TChart;
begin
//save to stream
tmpStream:=TMemoryStream.Create;
SaveChartToStream(Chart1, tmpStream, false);
//load from stream
tmpStream.Position:=0;
tmpChart:=TChart.Create(Self);
LoadChartFromStream(tmpChart, tmpStream);
Chart2.Assign(tmpChart);
tmpStream.Free;
tmpChart.Free;
end;
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
Re: Scope of TChart.Assign method
Yeray,
That's not quite what I'm trying to do. The saved chart stores properties of the TChart and properties of each of its TChartSeries. I want to recover these series properties as well as the chart properties.
If I slightly modify your code as below, then clicking the button updates Chart2 with the View3D property of Chart1, and sure, it leaves the data on Chart2 untouched, but it doesn't update the series ColorEachPoint property on Chart2.
Using the TChartSeries.Assign method won't work because it will delete all the existing data points. Are there any other methods I might use, without having to shunt the data into a temporary array? I wasn't really aware of chart themes. Would that mechanism achieve what I want to do?
That's not quite what I'm trying to do. The saved chart stores properties of the TChart and properties of each of its TChartSeries. I want to recover these series properties as well as the chart properties.
If I slightly modify your code as below, then clicking the button updates Chart2 with the View3D property of Chart1, and sure, it leaves the data on Chart2 untouched, but it doesn't update the series ColorEachPoint property on Chart2.
Using the TChartSeries.Assign method won't work because it will delete all the existing data points. Are there any other methods I might use, without having to shunt the data into a temporary array? I wasn't really aware of chart themes. Would that mechanism achieve what I want to do?
Code: Select all
with Chart1.AddSeries(TBarSeries) as TBarSeries do
begin
ColorEachPoint:=true;
FillSampleValues();
end;
Chart1.View3D := False;
with Chart2.AddSeries(TBarSeries) as TBarSeries do
begin
ColorEachPoint:=false;
FillSampleValues();
end;
Re: Scope of TChart.Assign method
Hello,
You can use AssignFormat to copy the properties from a series to another without copying the data.
Just add this at the Button1Click method, after assigning the chart properties:
You can use AssignFormat to copy the properties from a series to another without copying the data.
Just add this at the Button1Click method, after assigning the chart properties:
Code: Select all
Chart2[0].AssignFormat(tmpChart[0]);
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
Re: Scope of TChart.Assign method
Yeray,
Thanks for the advice. The AssignFormat works very well in all respects except one. If the series uses the default colour assigned automatically at series creation, that colour is not streamed to the saved chart. It then appears that when using the AssignFormat method, the colour of the target series is not updated as the property is not specified in the saved version. So I need to force the default series colour to be streamed. Is that possible?
If not I guess I have to abandon the default colouring and always set the series to some other colour that isn't the default.
In addition, how can I tell at run-time whether a series has it's default colour?
Regards
Toreba
Thanks for the advice. The AssignFormat works very well in all respects except one. If the series uses the default colour assigned automatically at series creation, that colour is not streamed to the saved chart. It then appears that when using the AssignFormat method, the colour of the target series is not updated as the property is not specified in the saved version. So I need to force the default series colour to be streamed. Is that possible?
If not I guess I have to abandon the default colouring and always set the series to some other colour that isn't the default.
In addition, how can I tell at run-time whether a series has it's default colour?
Regards
Toreba
Re: Scope of TChart.Assign method
Hello Toreba,
In this case, you actually want to copy a property TChart property from a chart to the other: the ColorPalette array. Note this array is used to color the points/series when you haven't explicitly assigned a color the points/series.
This ColorPalette array is exported to the stream, but if you don't assign the TChart, the default palette is used in the destination chart.
So you can assign the ColorPalette with this:
On the other hand, if the source series has the Colors explicitly assigned, then you'll have to manually copy them. The array of colors in a series isn't copied in the AssignFormat method because they are in close relation with the values; there's a color per each x and y value.
However, you can still copy the colors if you want. Here is how you can do it:
In this case, you actually want to copy a property TChart property from a chart to the other: the ColorPalette array. Note this array is used to color the points/series when you haven't explicitly assigned a color the points/series.
This ColorPalette array is exported to the stream, but if you don't assign the TChart, the default palette is used in the destination chart.
So you can assign the ColorPalette with this:
Code: Select all
Chart2.ColorPalette:=tmpChart.ColorPalette;
However, you can still copy the colors if you want. Here is how you can do it:
Code: Select all
TChartSeriesAccess = class(TChartSeries)
//...
uses Series, TeeThemes, TeeStore;
procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
ApplyChartTheme(TAndrosTheme, Chart1);
with Chart1.AddSeries(TBarSeries) as TBarSeries do
begin
ColorEachPoint:=true;
FillSampleValues();
//test with colors assigned
{for i:=0 to Count-1 do
ValueColor[i]:=AndroidPalette[i];}
end;
Chart1.View3D := False;
with Chart2.AddSeries(TBarSeries) as TBarSeries do
begin
ColorEachPoint:=false;
FillSampleValues();
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
Procedure AssignColors(Source: TChartSeries; Dest: TChartSeries);
var t : Integer;
begin
if Assigned(TChartSeriesAccess(Source).FColors) then
begin
if Assigned(TChartSeriesAccess(Dest).FColors) then
TChartSeriesAccess(Dest).FColors.Clear
else
TChartSeriesAccess(Dest).FColors:=TList{$IFDEF D18}<TColor>{$ENDIF}.Create;
for t:=0 to TChartSeriesAccess(Source).FColors.Count-1 do
TChartSeriesAccess(Dest).FColors.Add(TChartSeriesAccess(Source).FColors[t]);
end
else
FreeAndNil(TChartSeriesAccess(Dest).FColors);
end;
var tmpStream: TMemoryStream;
tmpChart: TChart;
i: Integer;
begin
//save to stream
tmpStream:=TMemoryStream.Create;
SaveChartToStream(Chart1, tmpStream, true);
//load from stream
tmpStream.Position:=0;
tmpChart:=TChart.Create(Self);
LoadChartFromStream(tmpChart, tmpStream);
Chart2[0].AssignFormat(tmpChart[0]);
Chart2.ColorPalette:=tmpChart.ColorPalette;
AssignColors(tmpChart[0], Chart2[0]);
tmpStream.Free;
tmpChart.Free;
end;
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |
Re: Scope of TChart.Assign method
Hi Yeray,
Thanks for the advice.
Actually, I am using the chart Assign method, so I think the ColorPalette is being copied successfully. But that's not the solution either. In a typical use case, the user does this:
- He creates a chart and accepts all the default colours. He maybe sets some text captions, but otherwise is happy with the default set-up;
- He saves the chart to stream (to database);
- Next session he reloads the chart from stream (from database) and all is well;
- He re-orders the series for clarity, but makes no other changes;
- He saves the chart to stream again. So, still. the saved version contains no explicit colours for series, and the colour palette is unchanged;
. Next session he reloads the chart, and finds that re-ordered series pick up the wrong default colour from the default color palette.
So if I understand you correctly, at some point in the history of the excellent TChart, it has been decided that it's better to treat the series color property as a default property, whose value comes from the color palette, rather than as a non-defaulted property which is easier for the coder to test and manipulate. Fair enough. But as I see it, my best way round this might be to introduce my own CustomColor property which I can save to and retrieve from the stream, and set that to record the actual series colour. Does that sound sensible to you?
Regards
Toreba
Thanks for the advice.
Actually, I am using the chart Assign method, so I think the ColorPalette is being copied successfully. But that's not the solution either. In a typical use case, the user does this:
- He creates a chart and accepts all the default colours. He maybe sets some text captions, but otherwise is happy with the default set-up;
- He saves the chart to stream (to database);
- Next session he reloads the chart from stream (from database) and all is well;
- He re-orders the series for clarity, but makes no other changes;
- He saves the chart to stream again. So, still. the saved version contains no explicit colours for series, and the colour palette is unchanged;
. Next session he reloads the chart, and finds that re-ordered series pick up the wrong default colour from the default color palette.
So if I understand you correctly, at some point in the history of the excellent TChart, it has been decided that it's better to treat the series color property as a default property, whose value comes from the color palette, rather than as a non-defaulted property which is easier for the coder to test and manipulate. Fair enough. But as I see it, my best way round this might be to introduce my own CustomColor property which I can save to and retrieve from the stream, and set that to record the actual series colour. Does that sound sensible to you?
Regards
Toreba
Re: Scope of TChart.Assign method
Hello Toreba,
Could you please arrange a simple example project we can run as-is to reproduce the problem here?
Thanks in advance.
Could you please arrange a simple example project we can run as-is to reproduce the problem here?
Thanks in advance.
Best Regards,
Yeray Alonso Development & Support Steema Software Av. Montilivi 33, 17003 Girona, Catalonia (SP) | |
Please read our Bug Fixing Policy |