Bottom axis labels

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Normand Peladeau
Newbie
Newbie
Posts: 30
Joined: Tue Dec 28, 2004 5:00 am
Contact:

Bottom axis labels

Post by Normand Peladeau » Wed Apr 05, 2006 12:45 pm

Is there a property or a way for me to check whether all labels on the bottom axis of a barchart are visible.

I would like to automatically adjust the display of those labels so that they are all visible. For example, if they are not all visible, try to set the LabelAlternate to True, if still not all visible, set the LabelAngle to 90.

Any idea how I can do this?

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Wed Apr 05, 2006 12:53 pm

Hi Normand,

You may check it in the OnGetAxisLabel event. There you have the ValueIndex parameter so that you can check if all points in a series had their labels drawn.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Normand Peladeau
Newbie
Newbie
Posts: 30
Joined: Tue Dec 28, 2004 5:00 am
Contact:

Post by Normand Peladeau » Wed Apr 05, 2006 1:38 pm

I tried the following code:

IF (Sender = BarChart.BottomAxis) AND (ValueIndex > -1) and (LabelText <> '') then begin
Inc(NbLabels);
end;

But NbLabels is always equal to the number of values, and does not correspond to the number of labels drawn on the bottom axis.

Pep
Site Admin
Site Admin
Posts: 3303
Joined: Fri Nov 14, 2003 5:00 am
Contact:

Post by Pep » Tue Apr 11, 2006 11:56 am

Hi,

you could use similar code to the following, cheking how many labels has been displayed, and if they are less than the Series count set as Alternate, and the same should work when angle is necessary :

Code: Select all

Function IsFloatingPoint(const S : string): boolean;
  Var
    iCount  : integer;
    fNumber : extended;
  begin
     Val(s, fNumber, iCount);
     result := (iCount>0);
  end;

procedure TForm1.Chart1GetAxisLabel(Sender: TChartAxis;
  Series: TChartSeries; ValueIndex: Integer; var LabelText: String);
begin
  if (Sender = Chart1.Axes.Bottom) and  not IsFloatingPoint(labeltext) then
    inc(i);
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if i<Series1.Count then
    Chart1.Axes.Bottom.LabelsAlternate:=True;
end;

Normand Peladeau
Newbie
Newbie
Posts: 30
Joined: Tue Dec 28, 2004 5:00 am
Contact:

Post by Normand Peladeau » Thu Apr 13, 2006 12:19 am

Sorry but I have no idea what you are talking about.

Suppose I have 20 labels associated with 20 values and I need to draw a barchart. If the barchart is too narrow, it may draw only 8 or 9 labels. None of them are numerical values. Even if I implement your method, I will always get back a value of 20. What I want is to know, if only 8 labels were drawn (because there was only space for 8), I want to get this number of 8.

I may then compare this number with the actual number of labels to be displayed and take corrective action (reducing font size, changing the angle, etc.).

Pep
Site Admin
Site Admin
Posts: 3303
Joined: Fri Nov 14, 2003 5:00 am
Contact:

Post by Pep » Tue Apr 18, 2006 10:54 am

Hi,
back a value of 20. What I want is to know, if only 8 labels were drawn (because there was only space for , I want to get this number of 8.
This value is not calculated automatically, the only way to know how many labels has been displayed in the Axis would be by checking each axis label size and compare the sum of all with the axis size.

If you are source code customer you can add a var which saves this value in the TeEngine.pas unit.

I've added this feature on our wish list to be considered for further releases.

Normand Peladeau
Newbie
Newbie
Posts: 30
Joined: Tue Dec 28, 2004 5:00 am
Contact:

Post by Normand Peladeau » Tue Apr 18, 2006 11:25 am

the only way to know how many labels has been displayed in the Axis would be by checking each axis label size and compare the sum of all with the axis size..
Actually, it should be the size of the longest one multiplied by the total number of labels, since while most labels may be short, and may be displayed, a longer label may still not be displayed because of its size. And I would also have to take into account the minimum separation property.
I've added this feature on our wish list to be considered for further releases.
A function that returns either the number of labels displayed or simply a boolean value indicating whether some labels were not drawn would be good enough.

Thanks!

SiA
Newbie
Newbie
Posts: 43
Joined: Wed Mar 10, 2004 5:00 am

Post by SiA » Mon Jun 16, 2008 1:59 pm

Pep wrote:I've added this feature on our wish list to be considered for further releases.
Hi Pep,

Sorry for bumping this topic. Is this feature available in 7.12?
If not, please tell me how to know if all labels are displayed before drawing chart?

I'm try to set the LabelAngle to 90 like Normand, but I afraid using OnGetAxisLabel will make chart blinked.

Thanks in advance!

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Mon Jun 16, 2008 2:33 pm

Hi SiA,

No, this feature hasn't been implemented.

To achieve what you request you may be interested on reading this thread where almost all options about this subject were being discussed. This is a TeeChart for .NET thread but the same applies to the VCL version. Notice this is a long thread (several pages) and what you are looking for may not appear until last pages.

Hope this helps!
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

SiA
Newbie
Newbie
Posts: 43
Joined: Wed Mar 10, 2004 5:00 am

Post by SiA » Tue Jun 17, 2008 5:15 am

Hi Narcís,

Thanks for the interesting thread. It took me a lot of time to read :?
I can see why you remember it for such a long time :wink:

Here are some results:
1/ I have many charts without using custom labels. Does the method you and Werner mentioned at the end still work?

2/ I found the Bitmap() method is very helpful. I think what it does is drawing the chart in memory, not the real GUI. Is it right? What is the equivalent method in VCL? I found TeeCreateBitmap, but not sure if it's right.

3/ Actually, I have my own solution to calculate angle:

Code: Select all

function CalculateAngle(
  ALabelSeries: TChartSeries): integer;
var
  i, ItemCount: Integer;
  OldLabelPos, OldLabelSize, tmpLabelPos, tmpLabelSize: Integer;
  CanDraw, NoLabelSeries: Boolean;
  BottomAxis: TChartAxis;
  CurrentValue: Double;
  CurrentLabel: String;
begin
  OldLabelPos := -1;
  OldLabelSize := 0;
  CanDraw := True;
  NoLabelSeries := ALabelSeries = nil;
  Chart.Repaint; //Chart.TeeCreateBitmap;
  BottomAxis := Chart.BottomAxis;
  if NoLabelSeries then
    ItemCount := BottomAxis.Items.Count
  else
    ItemCount := ALabelSeries.Count;


  for i := 0 to ItemCount-1 do
  begin
    if NoLabelSeries then
    begin
      CurrentValue := BottomAxis.Items[i].Value;
      CurrentLabel := BottomAxis.Items[i].Text;
    end
    else
    begin
      CurrentValue := ALabelSeries.XValues[i];
      CurrentLabel := ALabelSeries.XLabel[i];
    end;

    if (CurrentValue >= BottomAxis.Minimum) and
       (CurrentValue <= BottomAxis.Maximum) then
    begin
      tmpLabelPos := BottomAxis.CalcPosValue(CurrentValue);
      tmpLabelSize := Chart.Canvas.TextWidth(CurrentLabel);

      if (OldLabelPos<>-1) then
      begin
        tmpLabelSize := tmpLabelSize div 2;

        if tmpLabelPos >= OldLabelPos then
          CanDraw := (tmpLabelPos-tmpLabelSize-20) >= (OldLabelPos+OldLabelSize)
        else
          CanDraw := (tmpLabelPos+tmpLabelSize+20) <= (OldLabelPos-OldLabelSize);

        if not CanDraw then break;

        OldLabelPos := tmpLabelPos;
        OldLabelSize := tmpLabelSize;
      end
      else
      begin
        OldLabelPos := tmpLabelPos;
        OldLabelSize := tmpLabelSize div 2;
      end;
    end;
  end;

  if not CanDraw
    then Result := 90
    else Result := 0;
end;
When I use the normal labels, I input the series that generates labels in bottom axis.
When I use custom labels, I put nil as an input.
It works quite well.
However, I don't want to call Chart.Repaint as it draw chart in GUI and give blinking effect. Changing it to Chart.TeeCreateBitmap gives me the same result (most of the times), but it crash sometime.
I want to know what it really does.

4/ By the way, I think:

Code: Select all

      tmpLabelPos := BottomAxis.CalcPosValue(CurrentValue);
      tmpLabelSize := Chart.Canvas.TextWidth(CurrentLabel);
do not give right values every times. Am I using it properly in this case?

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Tue Jun 17, 2008 7:25 am

Hi SiA,
1/ I have many charts without using custom labels. Does the method you and Werner mentioned at the end still work?
Yes, I think this should still work.
2/ I found the Bitmap() method is very helpful. I think what it does is drawing the chart in memory, not the real GUI. Is it right? What is the equivalent method in VCL? I found TeeCreateBitmap, but not sure if it's right.
Yes, the VCL equivalent is this:

Code: Select all

Chart1.Draw;
4/ By the way, I think:
Code:
tmpLabelPos := BottomAxis.CalcPosValue(CurrentValue);
tmpLabelSize := Chart.Canvas.TextWidth(CurrentLabel);
do not give right values every times. Am I using it properly in this case?
You may need to use them after calling the Draw method.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

SiA
Newbie
Newbie
Posts: 43
Joined: Wed Mar 10, 2004 5:00 am

Post by SiA » Tue Jun 17, 2008 8:38 am

Hi Narcís,
Yes, the VCL equivalent is this:

Code: Select all

Chart1.Draw;
This method draws the chart to GUI. I don't want to draw chart.
You may need to use them after calling the Draw method.
As I said, this method just draw chart to GUI and doesn't update anything. I always get wrong values when call:

Code: Select all

tmpLabelPos := BottomAxis.CalcPosValue(CurrentValue);
tmpLabelSize := Chart.Canvas.TextWidth(CurrentLabel); 
Let me summary what I need:
I want to update chart (all chart values) without drawing it to GUI

I cannot use your solution because it uses custom labels. I don't want to use custom labels in some charts of my project.
Please, could you tell a way to get right length values without doing anything to GUI?

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Tue Jun 17, 2008 8:46 am

Hi SiA,

I'm not sure if you want to get maximum label width or the number of visible labels. For the first option you could use MaxLabelsWidth property:

Code: Select all

Chart1.Axes.Bottom.MaxLabelsWidth
If this doesn't help don't hesitate to let us know.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

SiA
Newbie
Newbie
Posts: 43
Joined: Wed Mar 10, 2004 5:00 am

Post by SiA » Tue Jun 17, 2008 10:09 am

Hi Narcís,

Chart.Axes.Bottom.MaxLabelsWidth is the width of longest label or the width of all visible labels?

Anyway, I don't want to get either of them.

I want to get the width of each visible label
-and-
I want to get the position of each visible label

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

Post by Yeray » Tue Jun 17, 2008 11:12 am

Hi SiA,

I'm not able to reproduce it here. could you try the following code?
Note that there's a line series, a memo and a button added at design time.

Code: Select all

procedure TForm1.Button1Click(Sender: TObject);
var i: integer;
begin
  Memo1.Clear;

  for i:=0 to Chart1.Axes.Left.Items.Count-1 do
  begin
    if Chart1.Axes.Left.Items.Item[i].Visible then
    Memo1.Lines.Add('label: ' + floattostr(Chart1.Axes.Left.Items.Item[i].Value) +
    '   width: ' + inttostr(Chart1.Axes.Left.Items.Item[i].Width) + '   Left: ' +
    inttostr(Chart1.Axes.Left.Items.Item[i].ShapeBounds.Left) + '   Top: ' +
    inttostr(Chart1.Axes.Left.Items.Item[i].ShapeBounds.Top));

  end;
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

Post Reply