3

サブコンポーネント (TChart) が 2 回作成されているように見える Delphi で、保存された複合コンポーネントをリロードする際に問題があります。コードでコンポーネントを作成すると、正常に動作します。

私のコンポーネントは、クライアントに合わせた TChart をホストする TPanel であり、単一のシリーズとそのデータを自分で作成します。これが私のコードです:

type

  TMyChart = class( TPanel )
  PRIVATE
    FChart : TChart;
  PROTECTED
    procedure Notification( AComponent : TComponent; Operation : TOperation ); override;
  PUBLIC
    constructor Create( AOwner : TComponent ); override;
    destructor  Destroy; override;
  PUBLISHED
    property Chart : TChart
               read FChart;
  end;


{ TMyChart }

constructor TMyChart.Create(AOwner: TComponent);
begin
  inherited;
  Width := 400;
  Height := 150;
  FChart := TChart.Create( Self );
  FChart.Name := '';
  FChart.SetSubComponent( True );
  FChart.FreeNotification( Self );
  FChart.Parent := Self;
  FChart.Align := alClient;
  FChart.AddSeries( TLineSeries.Create( FChart ));
  FChart.Series[0].FillSampleValues(100);
end;

destructor TMyChart.Destroy;
begin
  FreeAndNil( FChart );
  inherited;
end;

procedure TMyChart.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (AComponent = FChart) and (Operation = opRemove) then
    FChart := nil;
end;

initialization

  RegisterClass( TMyChart );
  RegisterClass( TChart );
  RegisterClass( TLineSeries );

end.

ExtCtrls 'TLabeledEdit' の例に従って、サブコンポーネント TChart の FreeNotification を含めました。

TStream.WriteComponent を使用してこれをストリーミングし、次の DFM を取得します。

object Mychart1: TMyChart
  Left = 0
  Top = 0
  Width = 400
  Height = 150
  Caption = 'Mychart1'
  TabOrder = 3
  Chart.Left = 1
  Chart.Top = 1
  Chart.Width = 398
  Chart.Height = 148
  Chart.Align = alClient
  Chart.TabOrder = 0
  Chart.ColorPaletteIndex = 13
  object TChart
    Left = 1
    Top = 1
    Width = 398
    Height = 148
    Align = alClient
    TabOrder = 0
    ColorPaletteIndex = 13
    object TLineSeries
      Marks.Arrow.Visible = True
      Marks.Callout.Brush.Color = clBlack
      Marks.Callout.Arrow.Visible = True
      Marks.ShapeStyle = fosRoundRectangle
      Marks.Visible = False
      Brush.BackColor = clDefault
      Pointer.InflateMargins = True
      Pointer.Style = psRectangle
      Pointer.Visible = False
      XValues.Name = 'X'
      XValues.Order = loAscending
      YValues.Name = 'Y'
      YValues.Order = loNone
    end
  end
end

私が必要とするすべてがそこにあります。次のように、ReadComponent を使用してこの DFM をリロードします。

procedure LoadComponentFromFile( var AComponent : TComponent );
var
  MS : TMemoryStream;
  SS : TStringStream;
begin
  MS := TMemoryStream.Create;
  SS := TStringStream.Create;
  try
    SS.LoadFromFile( GetSpecialFolderPath( CSIDL_DESKTOP ) + '\test.txt' );
    SS.Position := 0;
    ObjectTextToBinary( SS, MS );
    MS.Position := 0;
    AComponent := MS.ReadComponent( nil );
  finally
    MS.Free;
    SS.Free;
  end;
end;

procedure TForm8.Button3Click(Sender: TObject);
begin
  FreeAndNil( FMyChart );

  LoadComponentFromFile( TComponent(FMyChart) );

  FMyChart.Parent := Self;
end;

この後、2 つの TCharts が作成されたようです。1 つは正しいシリーズ データ (TMyChart.Create によって作成) を持ち、もう 1 つ (この前) は空の軸を持ち、おそらく ReadComponent が 'オブジェクト TChart' を作成している場所です。「TMyChart.Create」にブレークポイントを配置し、「TCustomChart.Create」の TChart のソース コードに別のブレークポイントを配置して、これを証明しました。ローダ コードを呼び出すと、最初に TMyChart.Create ブレークポイントに 1 回ヒットし、次に TCustomChart.Create ブレークポイントに 2 回ヒットします。サブコンポーネント TChart を再作成しないように TStream.ReadComponent に指示する必要があることはわかりますが、多くの試行とコンポーネント ストリーミングに関するドキュメントを読んだ後、それを構造化する方法がわかりません。誰でもコメントできますか?どうもありがとう。

4

0 に答える 0