Page 1 of 1

Undesired effect from code added values to TLineSeries help!

Posted: Wed Aug 18, 2010 7:24 pm
by 10546805
Version: 8.01.10798

I have a problem when I'm populating a TLineSeries with values through code:

Code: Select all

for iC := 0 to slReadingTypes.Count - 1 do
   begin
      csSeries := TLineSeries.Create(self);
      csSeries.Marks.ArrowLength := 1;
      csSeries.Pointer.Style := psCircle;
      csSeries.Pointer.Visible := true;
      csSeries.Pointer.Size := 2;
      csSeries.XValues.DateTime := true;
      csSeries.Title := slReadingTypes[iC];

      fraGTGraphNew.chtGraph.AddSeries(csSeries);

      ldsGraph.Filtered := True;
      ldsGraph.Filter := 'READTYPE = ''' + slReadingTypes[iC] + '''';
      ldsGraph.First;

      while not ldsGraph.eof do
      begin
         csSeries.AddXY(ldsGraph['TESTDATE'],ldsGraph['READING']);
         ldsGraph.Next;
      end;

   end;
The code is evoked after the form and the chart have been created, it's triggered withing an OnShow tab object event.
Perhaps I'm populating the values at an incorrect time?

The problem is that when I for example add only two dates (i.e. 1/5/2007 and 7/2/2009) the Bottom Axis displays ticks for values which don't exist and is a very undesirable formatting problem (so on the bottom axis instead of only seeing 1/5/2007 and 7/2/2009 and nothing in between I see all dates in between and the Y-Axis values aren't even aligned with the Bottom Axis grid).
Normally when a Client Data Set is assigned to a series it only shows values which exist.

I spend quite a bit of time playing around with the Chart settings, as well as somehow trying to tell the Chart through code to only display ACTUAL values, but I can't seem to be able to figure it out.

Please help, I've been stuck with this problem for quite some time now and need to have it corrected before our next release (which is scheduled very soon).

I can't attach a screen shot "Sorry, the board attachment quota has been reached."

Marcin.

Re: Undesired effect from code added values to TLineSeries help!

Posted: Fri Aug 20, 2010 7:48 am
by yeray
Hi Marcin,

If I understand well, you want the axis labels to only show values where there is a point (something like talText and talMark LabelStyle but showing Values instead of labels or the mark text).
It is already in the wish list to be implemented asap (TV52015098) a new LabelStyle to do it.

In the meanwhile you could use talText LabelStyle and format the text shown with OnGetAxisLabel. Something as following:

Code: Select all

uses Series;

procedure TForm1.FormCreate(Sender: TObject);
var point1: TPointSeries;
begin
  Chart1.View3D:=false;

  point1:=Chart1.AddSeries(TPointSeries) as TPointSeries;
  point1.XValues.DateTime:=true;
  point1.FillSampleValues(4);

  Chart1.Axes.Bottom.LabelStyle:=talText;
end;

procedure TForm1.Chart1GetAxisLabel(Sender: TChartAxis;
  Series: TChartSeries; ValueIndex: Integer; var LabelText: String);
begin
  if ((Sender = Chart1.Axes.Bottom) and (Sender.LabelStyle = talText)) then
  begin
    if ((Series <> nil) and (ValueIndex > -1)) then
    begin
      if (Sender.IsDateTime) then
        LabelText:=FormatDateTime(Sender.DateTimeFormat, Series.XValues[ValueIndex])
      else
        LabelText:=FloatToStr(Series.XValues[ValueIndex]);
    end;
  end;
end;

Re: Undesired effect from code added values to TLineSeries help!

Posted: Fri Aug 20, 2010 3:09 pm
by 10546805
That's actually exactly what I needed.
To show only Bottom Labels where there is a point. No need for anything else here, just displaying the date's only for points with values. It works like a charm.

Perfect!

Thank you so much!

Marcin.

Re: Undesired effect from code added values to TLineSeries help!

Posted: Fri Aug 20, 2010 3:25 pm
by yeray
Hi Marcin,

You're welcome!

Re: Undesired effect from code added values to TLineSeries help!

Posted: Fri Aug 20, 2010 3:28 pm
by 10546805
Hmm.

Except now my Bottom Axis Title, and Bottom aligned Legend don't format properly and the Labels run into those elements.
Any suggestions?

Re: Undesired effect from code added values to TLineSeries help!

Posted: Mon Aug 23, 2010 10:48 am
by yeray
Hi Marcin,

I've added the following code to the example above but couldn't reproduce any problem.

Code: Select all

  Chart1.Axes.Bottom.LabelStyle:=talText;
  Chart1.Axes.Bottom.Title.Caption:='My bottom axis title';
  Chart1.Legend.Alignment:=laBottom;
Anyway, it's possible that you'll have to calculate and define the margins manually, and maybe the legend position too.

Re: Undesired effect from code added values to TLineSeries help!

Posted: Mon Aug 23, 2010 3:27 pm
by 10546805
Unfortunately the formatting does get messed up for me.
I tried a variety of things, such as trying to repaint/refresh the chart or it's objects at different trigger times.
I was unable do correct the issue.

I did hope for setting some form of padding/spacing/margins on these objects (i.e. the Bottom Title and the Legend) but I'm having a really hard time finding a place where I could set any of these (in either the Chart Editor or in code).

I have to get this compiled and out the door by tomorrow. Any additional help would be appreciated!

Re: Undesired effect from code added values to TLineSeries help!

Posted: Tue Aug 24, 2010 9:21 am
by yeray
Hi Marcin,

We'll be pleased to try to find a way that works for you if we can reproduce the problem here so please, try to arrange a simple example project we can run as-is to reproduce the problem here.
My suspect is that you could be suffering a similar problem to what has been discussed here but an example project would help us to understand the problem better.

Re: Undesired effect from code added values to TLineSeries help!

Posted: Tue Aug 24, 2010 1:53 pm
by 10546805
graphissuesbottomx.jpg
graphissuesbottomx.jpg (120.79 KiB) Viewed 13104 times
This is the screen shot of the issue I am having.
The axis title and the legend are not shifted relative to the height of the labels, or maybe rather the chart area is not shifting leaving enough margin for the title and legend not to overlap.

My code still remains the same as mentioned above with the addition of what you described for the talText setting and the GetAxisLabel code.

Re: Undesired effect from code added values to TLineSeries help!

Posted: Tue Aug 24, 2010 2:00 pm
by 10546805
In addition the chart on run time goes through this initialization:

Code: Select all

procedure miChartInit(Graph: TDBChart;
   ReadLabelFlag: boolean;
   {FilterReadingLabel: string;}
   const XAxisLabelPosition: String {= 'horizontal'};
   const LeftAxisMaxOffset: integer {= 5};
   const RightAxisMaxOffset: integer {= 5};
   const BottomAxisMinOffset: integer {= 5};
   const BottomAxisMaxOffset: integer {= 5};
   const HideReadingLabels: string {= ''});
var
   iC: integer;
   bSetClipFlag: boolean;
begin

   ReadLabelFlag:= false;

   bSetClipFlag:= false;

   with Graph do
   begin

      for iC := 0 to Axes.Count - 1 do
         Axes[iC].Title.Font.InterCharSize:=0;


      LeftAxis.LabelsAngle:= 0;
      RightAxis.LabelsAngle:= 0;

      LeftAxis.MaximumOffset:= LeftAxisMaxOffset;
      RightAxis.MaximumOffset:= RightAxisMaxOffset;
      BottomAxis.MinimumOffset := BottomAxisMinOffset;
      BottomAxis.MaximumOffset := BottomAxisMaxOffset;

      ShowHint := false;

      if XAxisLabelPosition = 'horizontal' then
         BottomAxis.LabelsAngle:= 0
      else if XAxisLabelPosition = 'vertical' then
         BottomAxis.LabelsAngle:= 90
      else
         BottomAxis.LabelsAngle:= 0;

         Legend.CheckBoxes:= true;
         Legend.ShapeStyle:= fosRoundRectangle;
         Legend.RoundSize:= 15;
         Legend.ShadowSize:= 0;
         Legend.Alignment:= laBottom;

         Zoom.Pen.SmallDots:= true;
         Zoom.Pen.Color:= clWhite;
         Zoom.Brush.Style:= bsSolid;
         Zoom.UpLeftZooms:= true;
         Zoom.Brush.Color:= 8454016;

         Zoom.MouseButton:= mbLeft;
         ScrollMouseButton:= mbLeft;

         Title.Font.Color:= 0;
         Title.Font.Size:= 10;
         Title.Font.Style:= Title.Font.Style + [fsBold];
         Title.Font.InterCharSize:= 0;

         Color:= cl3DLight;

      for iC := 0 to SeriesCount - 1 do
      begin
         Series[iC].Marks.Visible:= false;
         Series[iC].Marks.Clip:=false;
         Series[iC].Marks.Font.Size:= 8;
         Series[iC].Marks.ArrowLength:= 1;
         Series[iC].Marks.Shadow.Visible:=false;
      end;
   end;

   miClipReadingLabels(Graph,false,bSetClipFlag);

end;
Perhaps you see something in there which may potentially be causing this issue?

Re: Undesired effect from code added values to TLineSeries help!

Posted: Tue Aug 24, 2010 3:19 pm
by 10546805
The issue was with not having any Series created on FormCreate.
Adding series later on (on ShowTab) was not formatting the chart properly.

I had to create a dummy series, I actually did it through the Chart Editor, which is assigned to a DataSet and holds X/Y values but is manually hidden from displaying anything.
That corrected the formatting.

Issue solved.

Re: Undesired effect from code added values to TLineSeries help!

Posted: Tue Aug 24, 2010 4:28 pm
by yeray
Hi Marcin,

Once the axes labels are formatted with OnGetAxisLabels event, the margin and the position where the axis title has to be drawn isn't calculated so you have to do manually.
This is a very similar case to the thread mentioned above, where a new LabelStyle would avoid you to do all these manual calculations (TV52015098/TF02015095).
In your case, you also need an axis title and the position where the axis title has to be drawn isn't accessible so I'll suggest you to use an AnnotationTool to draw the axis title where you've calculated.
Here it is an example:

Code: Select all

uses Series, Math, TeeTools;

var maxLabelsWidthBottom: Integer;

procedure TForm1.FormCreate(Sender: TObject);
var point1: TPointSeries;
begin
  Chart1.Align:=alClient;
  Chart1.View3D:=false;

  point1:=Chart1.AddSeries(TPointSeries) as TPointSeries;
  point1.XValues.DateTime:=true;
  point1.FillSampleValues(8);

  Chart1.Axes.Bottom.LabelStyle:=talText;

  Chart1.Axes.Bottom.LabelStyle:=talText;
  Chart1.Axes.Bottom.Title.Caption:='My bottom axis title';
  Chart1.Axes.Bottom.Title.Visible:=false;
  Chart1.Legend.Alignment:=laBottom;
  Chart1.Legend.CustomPosition:=true;

  Chart1.Axes.Bottom.LabelsAngle:=90;

  with Chart1.Tools.Add(TAnnotationTool) as TAnnotationTool do
  begin
    Text:=Chart1.Axes.Bottom.Title.Caption;
    Shape.Visible:=false;
  end;

  Chart1.Draw;
end;

procedure TForm1.Chart1AfterDraw(Sender: TObject);
begin
  AdjustMarginsAndLegend;
end;

procedure TForm1.Chart1GetAxisLabel(Sender: TChartAxis;
  Series: TChartSeries; ValueIndex: Integer; var LabelText: String);
begin
  if ((Sender = Chart1.Axes.Bottom) and (Sender.LabelStyle = talText)) then
  begin
    if ((Series <> nil) and (ValueIndex > -1)) then
    begin
      if (Sender.IsDateTime) then
        LabelText:=FormatDateTime(Sender.DateTimeFormat, Series.XValues[ValueIndex])
      else
        LabelText:=FloatToStr(Series.XValues[ValueIndex]);

      if ValueIndex = 0 then
        maxLabelsWidthBottom:=Chart1.Canvas.TextWidth(LabelText)
      else
        maxLabelsWidthBottom:=Max(maxLabelsWidthBottom,Chart1.Canvas.TextWidth(LabelText));
    end;
  end;
end;

procedure TForm1.AdjustMarginsAndLegend;
var AnotTitle: TAnnotationTool;
begin
  Chart1.MarginUnits:=muPixels;

  AnotTitle:=Chart1.Tools[0] as TAnnotationTool;
  with Chart1.Axes.Bottom, Chart1.Canvas do
  begin
    Chart1.MarginBottom:=maxLabelsWidthBottom + TickLength + Chart1.Legend.Height + TextHeight(AnotTitle.Text);
    AnotTitle.Top:=Chart1.Height - Chart1.Legend.Height - TextHeight(AnotTitle.Text);
    AnotTitle.Left:=Round((Chart1.Width/2) - (TextWidth(AnotTitle.Text)/2));
  end;

  Chart1.Legend.Left:=Round((Chart1.Width/2) - (Chart1.Legend.Width/2));
  Chart1.Legend.Top:=Chart1.Height - Chart1.Legend.Height;
end;