Page 1 of 1

Customized axis labels

Posted: Sun Oct 21, 2007 10:46 pm
by 9341477
Hi all,

Background: Bottom axis displays values as a datetime (series' datetime property is set to true for that axis), Increment property equals to one hour and ExactDateTime is set to False because I didn't like that alternating label "effect" when panning the chart with mouse.

My problem is that when I keep zooming the chart in, there will be several labels showing the same date (e.g. 22.10.2007) at some point. To solve this problem, I modified the axis DateTimeFormat property to include the time portion as well. But this is not what I want, at least not always. I'd like to be able to display just a date portion in the label as long as there are only one label per day. When there are more than one label per day, I'd like to be able to display both date and time portions in the label.

Has anyone done something similar before?
Thanks!

Posted: Mon Oct 22, 2007 1:47 pm
by narcis
Hi Ivo,

Maybe you could use the OnGetAxisLabel event for that.

Hope this helps!

Posted: Mon Oct 22, 2007 2:23 pm
by 9341477
Hi NarcĂ­s,
narcis wrote:Maybe you could use the OnGetAxisLabel event for that.
Thanks for your suggestion. This does tell me where I'm supposed to insert my code, but it does not tell me how do I determine if there are more than one label for the same day in month, at that time. Do you have any idea?

Thanks, again.

Posted: Mon Oct 22, 2007 9:31 pm
by 9341477
Just talking to myself. One idea would be to determine the actual value of axis increment (not the desired value as held by the Increment property). Should this value be less than one, I would consider that as an indication that there are at least two or more labels for the same day.

I discovered that the (bottom) axis has a method called CalcIncrement, but it is of no practical use to me because I'm apparently not supposed to call this method from within the OnGetAxisLabel event, because at the time this event is triggered, the CalcIncrement method is already being called by the TeeChart code, which results in a stack overflow and complete application crash (tested).

Is there any other method how to obtain the actual value of (bottom) axis increment from within the OnGetAxisLabel event handler, other than by calling CalcIncrement method?

Thanks, again.

Posted: Wed Oct 24, 2007 8:54 am
by yeray
Hi ibauer,

As you suspected, the problem here is that OnGetAxisLabel event is executed before than the series is drawn, so this doesn't seem to be the appropriate event to acquire points positions.

Why don't you try to compare partial strings (at labels) to identify the same day points? I can't think an easier way actually.

Posted: Wed Oct 24, 2007 10:26 am
by 9341477
Hi Yeray,
9348257 wrote:Why don't you try to compare partial strings (at labels) to identify the same day points?
That might be possible (using TChartAxis.LabelValue method), but even then, how can I possibly know upfront at which data points the labels will appear? Note that we are still within the OnGetAxisLabel event handler.

Could you please provide a simplistic, but working example?

Posted: Tue Oct 30, 2007 10:03 am
by yeray
Hi ibauer,

If I understood well, you're trying to achieve something similar to the following. Note that we compare the maximum and minimum of the bottom axis and, if they are the same, we're showing only a day and we have to show only the 5 last characters of the Labels:

Code: Select all

procedure TForm1.Chart1GetAxisLabel(Sender: TChartAxis;
  Series: TChartSeries; ValueIndex: Integer; var LabelText: String);
begin
  if CompareDate(Chart1.Axes.Bottom.Minimum, Chart1.Axes.Bottom.Maximum) = 0 then
  begin
    LabelText := RightStr(LabelText,5);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i,j:Integer;
begin
  Series1.Clear;
  Series1.XValues.DateTime := true;

  Chart1.View3D := false;

  Chart1.Axes.Bottom.Increment := DateTimeStep[dtOneHour];
  Chart1.Axes.Bottom.ExactDateTime := false;
  Chart1.Axes.Bottom.DateTimeFormat := 'dd/mm/yyyy hh:mm';
  Chart1.Axes.Bottom.LabelsAlternate:=true;

  for i:=0 to 20 do
  begin
    for j:=0 to 3 do
      Series1.AddXY(EncodeDateTime(2007,11,i+1,j+1,0,0,0),random*100);
  end;
end;

Posted: Tue Oct 30, 2007 1:06 pm
by 9341477
Hi Yeray,
9348257 wrote:If I understood well, you're trying to achieve something similar to the following. Note that we compare the maximum and minimum of the bottom axis and, if they are the same, we're showing only a day and we have to show only the 5 last characters of the Labels:
Thanks, although this is not what I wanted, you made me experimenting and I now almost have a solution I'm after. This is the code that does not display the time portion of TDateTime unless there are more than one label for the same day (note that BottomAxis.RoundFirstLabel is set to True):

Code: Select all

procedure TMyFrame.ChartGetAxisLabel(Sender: TChartAxis;
  Series: TChartSeries; ValueIndex: Integer; var LabelText: string);
// BottomAxis.DateTimeformat := 'd.m. h:mm';
const
  CSubString = #32 + '0:00';
var
  LPos: Integer;
begin
  LPos := Pos(CSubString, LabelText);
  if LPos > 0 then
  begin
    Delete(LabelText, LPos, Succ(Length(LabelText) - LPos));
  end;
end;
Now my (only minor) problem is that the above code cuts the zero time portion of the label always, but I would like to keep it in there when more than one label is displayed for the same day. Is it possible?

Posted: Wed Nov 07, 2007 5:59 pm
by Pep
Hi Ivo,

you should be able to customize it saving each time the axis label that has been assigned in the OnGetAxisLabel event and before to customize it check if the saved label is the same day or not.

Posted: Sun Nov 11, 2007 7:40 pm
by 9341477
Hi Pep,

Thanks for your suggestion. I'll give it a go.

Ivo