サブコンポーネント (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 に指示する必要があることはわかりますが、多くの試行とコンポーネント ストリーミングに関するドキュメントを読んだ後、それを構造化する方法がわかりません。誰でもコメントできますか?どうもありがとう。