Page 2 of 2

Re: SubChart’s Series disappear

Posted: Thu Aug 13, 2020 11:06 am
by Christopher
Hello!
xsLiu wrote:
Thu Aug 13, 2020 1:28 am
If Charts have Margins (MarginTop, MarginBottom, MarginLeft, MarginRight) and Axes have Offsets (MinimumOffset, MaximumOffset), how to modify the code ?
The Margins require no code change, as they automatically change the ChartRect size - the Offsets do require a change, as they affect the values of pixelXUnit and pixelYUnit. In the following code, press Button1 to make changes and then the modified Button2 to see the results:

Code: Select all

procedure TForm1.Button1Click(Sender: TObject);
begin
    //VCLTee.EditChar.EditChart(Self, Chart1);
    Chart1.MarginUnits:=muPixels;
    Chart1.MarginBottom:=40;
    Chart1.MarginTop:=40;
    Chart1.MarginLeft:=40;
    Chart1.MarginRight:=40;

    Chart1.Axes.Left.MinimumOffset:=20;
    Chart1.Axes.Left.MaximumOffset:=20;
    Chart1.Axes.Bottom.MinimumOffset:=20;
    Chart1.Axes.Bottom.MaximumOffset:=20;
end;

procedure TForm1.Button2Click(Sender: TObject);
var charRect, subRect : TRect;
    pixelXUnit,pixelYUnit:Double;
    subBottomMax,subLeftMax:Double;
begin
    charRect:=Chart1.ChartRect;
    subRect:=SubChart.ChartRect;

    pixelXUnit:=(Chart1.Axes.Bottom.Maximum-Chart1.Axes.Bottom.Minimum)/(charRect.Width-Chart1.Axes.Bottom.MinimumOffset-Chart1.Axes.Bottom.MaximumOffset);
    pixelYUnit:=(Chart1.Axes.Left.Maximum-Chart1.Axes.Left.Minimum)/(charRect.Height-Chart1.Axes.Left.MinimumOffset-Chart1.Axes.Left.MaximumOffset);

    subBottomMax:=pixelXUnit*subRect.Width;
    subLeftMax:=pixelYUnit*subRect.Height;

    SubChart.Axes.Bottom.SetMinMax(Chart1.Axes.Bottom.Minimum, subBottomMax);
    SubChart.Axes.Left.SetMinMax(Chart1.Axes.Left.Minimum, subLeftMax);
end;

Re: SubChart’s Series disappear

Posted: Fri Aug 14, 2020 2:38 am
by 16586272
Your code makes it clear to me how to get SubChart.ChartRect. Really helpful, thanks a lot!!

In my app, the position (SubChart.Left, SubChart.Top) and size (SubChart.Width, SubChart.Height) of the SubChart are unkown at the beginning. I’m trying to display the SubChart by using SubChart.ChartRect as following, but the SubChart does not show its Series as mentioned earlier.
SubChart.CustomChartRect := true;
SubChart.ChartRect := TeeRect(SubLeft, SubTop, SubRight, SubBottom);
It seems that SubChart’s position/size and SubChart.ChartRect are different. If the values (Width, Height, etc.) of SubChart.ChartRect are assigned directly to that of SubChart, the pixel length are not exactly the same for both Chart and SubChart.
Is there any way to determine the position and size of the SubChart with SubChart.ChartRect?

Re: SubChart’s Series disappear

Posted: Fri Aug 14, 2020 12:08 pm
by Christopher
Hello,
Is there any way to determine the position and size of the SubChart with SubChart.ChartRect?
No, not really, because they are two different things. One thing is the position of the TWinControl relative to its parent (Left,Top) and its size (Width,Height), and another thing is the size of the area enclosed by the Chart axes (which is the ChartRect). You can see that if you run a TChart without a series added to it, the ChartRect is empty - this is becuase the series defines the axes, and the length of the axes define the ChartRect. So the ChartRect of your SubChart will be empty until you add a series to it.

What this means, in practice, is that the calculations in my example should be run at the same time as you add a series to your SubChart - as soon as you've added the series, you can call Repaint and obtain the values for ChartRect, e.g. (click Button1 then Button2)

Code: Select all

unit ChartTest;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VclTee.TeeGDIPlus, VCLTee.TeEngine,
  Vcl.ExtCtrls, VCLTee.TeeProcs, VCLTee.Chart, Vcl.StdCtrls, VCLTee.TeeWorldSeries, VCLTee.Series,
  VCLTee.TeeURL, VCLTee.TeeSeriesTextEd, VCLTee.TeeSubChart, VCLTee.EditChar;

type
  TForm1 = class(TForm)
    Chart1: TChart;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Chart1AfterDraw(Sender: TObject);
    procedure SubChartAfterDraw(Sender: TObject);
  private
    SubChartTool: TSubChartTool;
    SubChart: TChart;
    procedure AddSubChart(Resize: Boolean = True; AddSeries: Boolean = True);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.AddSubChart(Resize: Boolean; AddSeries: Boolean);
var t:Integer;
    rnd:Double;
begin
    SubChartTool:=TSubChartTool.Create(Self);
    Chart1.Tools.Add(SubChartTool);

    SubChart:=SubChartTool.Charts.AddChart('SubChart');

    if Resize then
    begin
        SubChart.View3D:=false;
        SubChart.Height:=300;
        SubChart.Width:=400;
        SubChart.Top:=10;
        SubChart.Left:=Chart1.Width-SubChart.Width-10;
    end;

    if AddSeries then
    begin
        SubChart.AddSeries(TLineSeries).FillSampleValues;
    end;

    SubChart.OnAfterDraw:=SubChartAfterDraw;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
    AddSubChart;

    Chart1.Repaint;

    ShowMessage('SubChart ChartRect: Width ' + IntToStr(SubChart.ChartRect.Width) );
end;

procedure TForm1.Button2Click(Sender: TObject);
var charRect, subRect : TRect;
    pixelXUnit,pixelYUnit:Double;
    subBottomMax,subLeftMax:Double;
begin
    if SubChart <> nil then
    begin
        charRect:=Chart1.ChartRect;
        subRect:=SubChart.ChartRect;

        pixelXUnit:=(Chart1.Axes.Bottom.Maximum-Chart1.Axes.Bottom.Minimum)/(charRect.Width-Chart1.Axes.Bottom.MinimumOffset-Chart1.Axes.Bottom.MaximumOffset);
        pixelYUnit:=(Chart1.Axes.Left.Maximum-Chart1.Axes.Left.Minimum)/(charRect.Height-Chart1.Axes.Left.MinimumOffset-Chart1.Axes.Left.MaximumOffset);

        subBottomMax:=pixelXUnit*subRect.Width;
        subLeftMax:=pixelYUnit*subRect.Height;

        SubChart.Axes.Bottom.SetMinMax(Chart1.Axes.Bottom.Minimum, subBottomMax);
        SubChart.Axes.Left.SetMinMax(Chart1.Axes.Left.Minimum, subLeftMax);
    end;
end;

procedure TForm1.SubChartAfterDraw(Sender: TObject);
var subX1,subX2:Integer;

  procedure DoBottomAxes;
  begin
      subX1:=SubChart.Axes.Bottom.CalcXPosValue(1);
      subX2:=SubChart.Axes.Bottom.CalcXPosValue(2);

      SubChart.Canvas.Pen.Color:=clRed;
      SubChart.Canvas.Pen.Width:=3;
      SubChart.Canvas.Line(subX1, SubChart.ChartRect.Bottom, subX2, SubChart.ChartRect.Bottom);
      SubChart.Canvas.Font.Color:=clRed;
      SubChart.Canvas.TextOut(subX1, SubChart.ChartRect.Bottom-20, 'Pixels: '+IntToStr(subX2-subX1));
  end;

  procedure DoLeftAxes;
  begin
      subX1:=SubChart.Axes.Left.CalcYPosValue(Chart1.Axes.Left.Minimum);
      subX2:=SubChart.Axes.Left.CalcYPosValue(Chart1.Axes.Left.Minimum + 50);

      SubChart.Canvas.Pen.Color:=clBlue;
      SubChart.Canvas.Pen.Width:=3;
      SubChart.Canvas.Line(SubChart.ChartRect.Left, subX1, SubChart.ChartRect.Left, subX2);
      SubChart.Canvas.Font.Color:=clBlue;
      SubChart.Canvas.TextOut(SubChart.ChartRect.Left+5, subX2, 'Pixels: '+IntToStr(subX1-subX2));
  end;
begin
    DoBottomAxes;
    DoLeftAxes;
end;

procedure TForm1.Chart1AfterDraw(Sender: TObject);
var charX1,charX2:Integer;

  procedure DoBottomAxes;
  begin
      charX1:=Chart1.Axes.Bottom.CalcXPosValue(1);
      charX2:=Chart1.Axes.Bottom.CalcXPosValue(2);

      Chart1.Canvas.Pen.Color:=clRed;
      Chart1.Canvas.Pen.Width:=3;
      Chart1.Canvas.Line(charX1, Chart1.ChartRect.Bottom, charX2, Chart1.ChartRect.Bottom);
      Chart1.Canvas.Font.Color:=clRed;
      Chart1.Canvas.TextOut(charX1, Chart1.ChartRect.Bottom - 20, 'Pixels: '+IntToStr(charX2-charX1));
  end;

  procedure DoLeftAxes;
  begin
      charX1:=Chart1.Axes.Left.CalcYPosValue(Chart1.Axes.Left.Minimum);
      charX2:=Chart1.Axes.Left.CalcYPosValue(Chart1.Axes.Left.Minimum + 50);

      Chart1.Canvas.Pen.Color:=clBlue;
      Chart1.Canvas.Pen.Width:=3;
      Chart1.Canvas.Line(Chart1.ChartRect.Left, charX1, Chart1.ChartRect.Left, charX2);
      Chart1.Canvas.Font.Color:=clBlue;
      Chart1.Canvas.TextOut(Chart1.ChartRect.Left+5, charX2, 'Pixels: '+IntToStr(charX1-charX2));
  end;
begin
    DoBottomAxes;
    DoLeftAxes;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    Chart1.OnAfterDraw:=Chart1AfterDraw;
    Chart1.AddSeries(TLineSeries).FillSampleValues;
end;

end.

Re: SubChart’s Series disappear

Posted: Sat Aug 15, 2020 9:59 am
by 16586272
My problems have been basically solved, except SubChart is roughly positioned.
Thanks for your clear explanations and detailed codes.