Setting custom position for chart legend

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
sde
Newbie
Newbie
Posts: 21
Joined: Fri Jun 21, 2013 12:00 am

Setting custom position for chart legend

Post by sde » Fri Jul 21, 2017 4:21 pm

In a project I’m working on, I have need for the legend on a chart to be completely centered in the middle of the chart. Unfortunately, setting TChart.Legend.Left and TChartLegend.Top using the 50% strategy does not work since this centers the top left corner of the legend and not the center of the legend.

So to try to get this to work, I tried setting “Chart1.Legend.CustomPosition := True” in the OnCreate of my form. And then I used the following OnGetLegendRect procedure for Chart1.

Code: Select all

procedure TfrmMain.Chart1GetLegendRect(Sender: TCustomChart; var Rect: TRect);
begin
  Sender.Legend.Left := Trunc((Sender.Width – (Rect.Right – Rect.Left)) / 2);
  Sender.Legend.Right := Trunc((Sender.Height – (Rect.Bottom – Rect.Top)) / 2);
end;
When I step through the debugger, Left and Right are correctly being set. However, when the form actually displays, it does not reflect that, and they are both set to zero with the legend in the top left corner.

Can you please help me understand what I might be doing wrong with this method?

Alternatively, I tried the following:

Code: Select all

procedure TfrmMain.Chart1GetLegendRect(Sender: TCustomChart; var Rect: TRect);
var
  iLegendWidth, iLegendHeight: Integer;
begin
  iLegendWidth := Rect.Right – Rect.Left;
  iLegendHeight := Rect.Bottom – Rect.Top;
  Rect.Left := Trunc((Sender.Width – iLegendWidth) / 2);
  Rect.Right := Rect.Left + iLegendWidth;
  Rect.Top := Trunc((Sender.Height – iLegendHeight) / 2);
  Rect.Bottom := Rect.Top + iLegendHeight;
end;
However, that only moves the legend itself and not the items in it. I see from the documentation that I am supposed to use OnGetLegendPosition but I’m not sure how to use X, Y, and XColor to do that. Could you please help with that?

Thanks!

Yeray
Site Admin
Site Admin
Posts: 9514
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Setting custom position for chart legend

Post by Yeray » Wed Jul 26, 2017 7:51 am

Hello,

The second approach looks correct to me. I see the texts need an extra repaint to be correctly positioned. Ie:

Code: Select all

uses Series;

var Chart1: TChart;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
begin
  Chart1:=TChart.Create(Self);
  Chart1.Parent:=Self;

  Chart1.Align:=alClient;
  Chart1.View3D:=False;
  Chart1.Legend.CustomPosition:=True;

  for i:=0 to 9 do
    Chart1.AddSeries(TPointSeries).FillSampleValues;

  Chart1.OnGetLegendRect:=Chart1GetLegendRect;

  Chart1.Draw; 
end;

procedure TForm1.Chart1GetLegendRect(Sender: TCustomChart; var Rect: TRect);
var
  iLegendWidth, iLegendHeight: Integer;
begin
  iLegendWidth := Rect.Right - Rect.Left;
  iLegendHeight := Rect.Bottom - Rect.Top;
  Rect.Left := Trunc((Sender.Width - iLegendWidth) / 2);
  Rect.Right := Rect.Left + iLegendWidth;
  Rect.Top := Trunc((Sender.Height - iLegendHeight) / 2);
  Rect.Bottom := Rect.Top + iLegendHeight;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

sde
Newbie
Newbie
Posts: 21
Joined: Fri Jun 21, 2013 12:00 am

Re: Setting custom position for chart legend

Post by sde » Wed Jul 26, 2017 6:54 pm

Hmm. Okay. Yes, I think that is correcting the problem for the display. I haven't gotten to this part yet, but one of the requirements for our program is to define a chart and directly export the chart to jpg/png/bmp/etc without having actually seen it displayed to the screen. So do you think calling the draw without displaying the chart will still do the trick in that kind of scenario, or do you think the exported image will have incorrect text placement?

Yeray
Site Admin
Site Admin
Posts: 9514
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Setting custom position for chart legend

Post by Yeray » Mon Jul 31, 2017 11:52 am

Hello,

You can try to force a chart repaint (actually two repaints) before exporting the chart to get the image.
However note there's a problem since v2016.19 where you can't force a repaint of a chart without a parent (#667). The workaround consists on using a temporal hidden form. Ie:

Code: Select all

uses Series;

var Chart1: TChart;

procedure TForm1.FormCreate(Sender: TObject);
var i: Integer;
    tmpForm: TForm;
begin
  Chart1:=TChart.Create(Self);
  //Chart1.Parent:=Self;

  Chart1.Align:=alClient;
  Chart1.View3D:=False;
  Chart1.Legend.CustomPosition:=True;

  for i:=0 to 9 do
    Chart1.AddSeries(TPointSeries).FillSampleValues;

  Chart1.OnGetLegendRect:=Chart1GetLegendRect;


  tmpForm:=TForm.Create(Self);
  tmpForm.Visible:=False;
  Chart1.Parent:=tmpForm;

  Chart1.Draw;
  Chart1.Draw;

  Image1.Picture.Bitmap:=Chart1.TeeCreateBitmap;

  Chart1.Parent:=nil;
  tmpForm.Destroy;
end;

procedure TForm1.Chart1GetLegendRect(Sender: TCustomChart; var Rect: TRect);
var
  iLegendWidth, iLegendHeight: Integer;
begin
  iLegendWidth := Rect.Right - Rect.Left;
  iLegendHeight := Rect.Bottom - Rect.Top;
  Rect.Left := Trunc((Sender.Width - iLegendWidth) / 2);
  Rect.Right := Rect.Left + iLegendWidth;
  Rect.Top := Trunc((Sender.Height - iLegendHeight) / 2);
  Rect.Bottom := Rect.Top + iLegendHeight;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

sde
Newbie
Newbie
Posts: 21
Joined: Fri Jun 21, 2013 12:00 am

Re: Setting custom position for chart legend

Post by sde » Tue Aug 01, 2017 7:34 pm

Good to know! Thank you.

Post Reply