delphichartsfiremonkeytmsdelphi-13-florence

How to have one axis for two series in TMS FNC Charts?


I've built the following Chart that shows temperatures. It shows the lowest and highest temperatures for each day:

Charts in an app built using the Delphi programming language

The issue I have is that there are two axis on the left and bottom. I want there to only be one left and one bottom.

How can this be achieved?


Let's take the bottom two axis as an example. They're both the exact same. I only need one. How can one be hidden or removed?


This is the code I use to make the chart:


procedure TForm1.Button1Click(Sender: TObject);
const
  CMin: array[1..31] of Double = (
    15, 16, 14, 13, 15, 17, 16, 14, 13, 12,
    15, 16, 18, 17, 16, 14, 15, 18, 19, 17,
    16, 15, 14, 13, 12, 14, 15, 17, 16, 15, 14
  );
  CMax: array[1..31] of Double = (
    28, 29, 30, 27, 26, 31, 32, 29, 28, 27,
    30, 31, 33, 32, 31, 29, 30, 33, 34, 32,
    31, 30, 29, 28, 27, 29, 30, 32, 31, 30, 29
  );
begin
    var lYear := 2025;
    var lMonth := 10;
    var lDaysInMonth := DaysInAMonth(lYear, lMonth);

    TemperatureChart.BeginUpdate;
    try
      TemperatureChart.Series.Clear;

      // Min series
      var sMin := TemperatureChart.Series.Add;
      sMin.LegendText := 'Min (�C)';
      sMin.XValues.MajorUnit := 1;
      sMin.XValues.MajorUnitFormat := '%.0f';
      sMin.YValues.MajorUnitFormat := '%.0f';

      // Max series
      var sMax := TemperatureChart.Series.Add;
      sMax.LegendText := 'Max (�C)';
      sMax.XValues.MajorUnit := 1;
      sMax.XValues.MajorUnitFormat := '%.0f';
      sMax.YValues.MajorUnitFormat := '%.0f';

      // Add points for each day of the selected month
      for var d := 1 to lDaysInMonth do
      begin
        with sMin.Points.Add do
        begin
          XValue := d;
          YValue := CMin[d];
        end;

        with sMax.Points.Add do
        begin
          XValue := d;
          YValue := CMax[d];
        end;
      end;

      // Update chart title
      var lMonthName := FormatDateTime('mmm', EncodeDate(lYear, lMonth, 1));
      TemperatureChart.Title.Text := Format('Temperature (Test Data) - %s %d', [lMonthName, lYear]);
    finally
      TemperatureChart.EndUpdate;
    end;
end;

Solution

  • Short answer: You need to let only one series "own" the visible axes, and put both series on common ranges. Give the first series the left/bottom positions, then give the second series no positions so it won’t request extra axes.

    You can add the following code to use the same left and bottom axis for both lines:

    // Use common ranges and force single left/bottom axis positions
    sMin.AutoYRange := arCommonZeroBased;
    sMin.AutoXRange := arCommon;
    sMin.YValues.Positions := [ypLeft];
    sMin.XValues.Positions := [xpBottom];
    
    // Share the same ranges; don't draw extra axes for this series
    sMax.AutoYRange := arCommonZeroBased;
    sMax.AutoXRange := arCommon;
    sMax.YValues.Positions := [];
    sMax.XValues.Positions := [];
    

    Screenshot:

    TMS FNC Charts

    Full Fixed code:

    procedure TForm1.Button1Click(Sender: TObject);
    const
      CMin: array[1..31] of Double = (
        15, 16, 14, 13, 15, 17, 16, 14, 13, 12,
        15, 16, 18, 17, 16, 14, 15, 18, 19, 17,
        16, 15, 14, 13, 12, 14, 15, 17, 16, 15, 14
      );
      CMax: array[1..31] of Double = (
        28, 29, 30, 27, 26, 31, 32, 29, 28, 27,
        30, 31, 33, 32, 31, 29, 30, 33, 34, 32,
        31, 30, 29, 28, 27, 29, 30, 32, 31, 30, 29
      );
    begin
        var lYear := 2025;
        var lMonth := 10;
        var lDaysInMonth := DaysInAMonth(lYear, lMonth);
    
        TemperatureChart.BeginUpdate;
        try
          TemperatureChart.Series.Clear;
    
          // Min series
          var sMin := TemperatureChart.Series.Add;
          sMin.LegendText := 'Min (°C)';
          sMin.XValues.MajorUnit := 1;
          sMin.XValues.MajorUnitFormat := '%.0f';
          sMin.YValues.MajorUnitFormat := '%.0f';
          // Use common ranges and force single left/bottom axis positions
          sMin.AutoYRange := arCommonZeroBased;
          sMin.AutoXRange := arCommon;
          sMin.YValues.Positions := [ypLeft];
          sMin.XValues.Positions := [xpBottom];
    
          // Max series
          var sMax := TemperatureChart.Series.Add;
          sMax.LegendText := 'Max (°C)';
          sMax.XValues.MajorUnit := 1;
          sMax.XValues.MajorUnitFormat := '%.0f';
          sMax.YValues.MajorUnitFormat := '%.0f';
          // Share the same ranges; don't draw extra axes for this series
          sMax.AutoYRange := arCommonZeroBased;
          sMax.AutoXRange := arCommon;
          sMax.YValues.Positions := [];
          sMax.XValues.Positions := [];
    
          // Add points for each day of the selected month
          for var d := 1 to lDaysInMonth do
          begin
            with sMin.Points.Add do
            begin
              XValue := d;
              YValue := CMin[d];
            end;
    
            with sMax.Points.Add do
            begin
              XValue := d;
              YValue := CMax[d];
            end;
          end;
    
          // Update chart title
          var lMonthName := FormatDateTime('mmm', EncodeDate(lYear, lMonth, 1));
          TemperatureChart.Title.Text := Format('Temperature (Test Data) - %s %d', [lMonthName, lYear]);
        finally
          TemperatureChart.EndUpdate;
        end;
    end;