6

MainForm は、実行時にいくつかのセカンダリ Frame オブジェクトを作成して、さまざまなオプション パネルを表示します。

これらのフレーム クラスの 1 つの典型的なコンストラクタを次に示します (それぞれ TFrame を拡張します)。

constructor Tframe2.Create(AOwner: TComponent);
begin
    inherited;
    edTime.Text := '12:00pm'; //edTime is a TEdit control. this line is where it throws the exception
    //etc.
end;

このコードは Delphi では正常に機能しましたが (正しい方法であったかどうかにかかわらず)、Lazarus の同じコードは EInvalidOperation 例外をスローし続けます。これは、コントロール (TEdit) に親の「ウィンドウ」がまだ割り当てられていない (rsControlHasNoParentWindow) ためです。コンストラクターが呼び出されるまで親が割り当てられないように見えるため、コードを調べると実際には意味があります。

セカンダリ フレームを初期化する MainForm のコードは次のとおりです。

if Assigned(frame) then FreeAndNil(frame);
case Node.AbsoluteIndex of
    optInterval: frame := Tframe2.Create(Self); //here's where the constructor gets called.
    //etc
end;
frame := TframeOther.Create(Self); 
if Assigned(frame) then
begin
    frame.Parent := panOptions; //here's where Tframe2's parent gets set
    frame.Align := alClient;
end;  

では、フォームの初期化シーケンスに関して、Delphi と Lazarus の間に重要な違いがあるかどうかを説明できる人はいますか?

そして、この種の初期化順序の問題を解決する最も標準的な方法は何でしょうか? 私がよく知っている他の言語と比較すると、このようなエラーを解決するための戦略が異なる場合があります。コンストラクターに別のパラメーターを追加するか、コンストラクターを事前に画面に描画して呼び出されるメソッドがある場合は、そのコードを再配置するか、ヘルパー メソッドを作成して setParent が呼び出された後に呼び出すことができます。ここで特定のベストプラクティスはありますか?

Edit]: これは何らかの形で TEdit に固有のもののようです。チェックボックスの状態を初期化する行には同じ問題がないようです。これは単に Lazarus のバグでしょうか?

4

1 に答える 1

1

さらに実験した後、TEditの親をフレームに設定する(フレームの親を設定するのではなく)行を追加することで、クラッシュの当面の問題のほとんどを解決することができました。そのようです:

edTime.Parent := Self;
edTime.Text := '12:00';

しかし、なぜこれが「時々」必要なのかをもっとよく理解したいと思います。

編集:これにより、TEditでテキストを設定できるようになりますが、コンポーネントを繰り返し処理し、チェックボックスのサイズを変更する自動サイズ変更コードは修正されません。どうやら、親セットを持たないフォームはまだ「一種の」問題です。

edit2:コンストラクターに2番目のパラメーターを追加し、コンストラクターでフォーム全体の親を設定すると、TEditの親を完全に設定する必要がなくなるようです。

于 2012-09-26T15:54:20.100 に答える