2016-11-24 14 views
2

Delphi 10.1のFiremonkeyで問題が発生しました。 私は FDateEdits_PositionとしてTPosition、及び FDateEdits_PositionSetが宣言されたプロパティDelphi 10.1 Firemonkey - コンポーネント構築時のプロパティ値

property EditDate_Position:TPosition read FDateEdits_Position write FDateEdits_PositionSet stored True; 

を作成したい(一部はTDateEditsような別の構成要素であるTLayout、に基づいて)新しいコンポーネントを作成します関数FDateEdits_PositionSet(値:TPosition)

成分の主コンストラクタは、コードから成る:

PointF.X:=10; 
PointF.Y:=30; 
FDateEdits_Position:=TPosition.Create(PointF); 

だからオブジェクトインスペクタにEditDate_Positionこのプロパティがあり、私はこの値を変更することができます。しかし、なぜ - コンパイルして実行した後、この値はConstructorのように値にリセットされますか? 私が実行しているときにこれらの行を除外するために

If (csDesigning in ComponentState) then 
begin 
    PointF.X:=10; 
    PointF.Y:=30; 
    FDateEdits_Position:=TPosition.Create(PointF); 
end; 

を使用しようとしましたが、プログラムがクラッシュ( FDateEditsが作成されません)。私はObject Inspectorを見ました - 値は正しくあり、それ以上です - .fmxファイルには適切な値があります。

どうすればいいですか?私はこの値がコンストラクタが実行されているときに開始点にあることに気づきましたが、少し後に(間隔= 1のTTimerでチェックされています)、適切な値をとります。

AfterConstructionプロシージャをオーバーライドするとこの問題は解決されず、適切な値で起動(作成時)する必要があります。その他:すべてがこの動作をしているわけではありません - ブール型のプロパティタイプはTPositionと似ていますが、TBitmapプロパティが正常に動作していることがわかります...

TPosition.Create )が、実行時にこれらのデフォルト値を設定せずにこれを作成する方法はありますか?

procedure TTest.FDateEdits_PositionSet(Value:TPosition); 
begin 
    FDateEdits_Position:=Value; 
    FDateEdits_Resize; 
end; 

(SELF)のいくつかのコンポーネントを移動 FDateEdits_Resize。

サンプルコードがあります(が、同じではない、それが簡略化されています):

unit Layout1; 

interface 

uses 
    System.SysUtils, System.Classes, FMX.Types, FMX.Controls, FMX.Layouts, 
    FMX.StdCtrls, System.Types; 

type 
    TLayout1 = class(TLayout) 
    private 
    { Private declarations } 
    FBtn:TButton; 
    FPosition:TPosition; 

    procedure FPositionSet(Value:TPosition); 
    protected 
    { Protected declarations } 
    public 
    { Public declarations } 
    constructor Create(AOwner:TComponent); override; 
    destructor Destroy; override; 
    published 
    { Published declarations } 
    property BtnPosition:TPosition read FPosition write FPositionSet; 
    end; 

procedure Register; 

implementation 

constructor TLayout1.Create(AOwner:TComponent); 
var 
    PointF:TPointF; 
begin 
    inherited Create(AOwner); 
    FBtn:=TButton.Create(Self); 
    FBtn.Parent:=Self; 
    FBtn.Stored:=False; 
    FBtn.Text:='Text'; 

    PointF.X:=10; 
    PointF.Y:=10; 
    FPosition:=TPosition.Create(PointF); 

    FBtn.Position.Assign(FPosition); 
end; 

destructor TLayout1.Destroy; 
begin 
    If FPosition<>nil then FPosition.Free; 
    If FBtn<>nil then FBtn.Free; 

    inherited; 
end; 

procedure TLayout1.FPositionSet(Value:TPosition); 
begin 
    FPosition.Assign(Value); 
    FBtn.Position.Assign(Value); 
end; 

procedure Register; 
begin 
    RegisterComponents('Samples', [TLayout1]); 
end; 

end. 

しかし、私は気づいたことだけで任意の結果を持っていない

Layout11.BtnPosition.X:=50; 
を呼び出し、ブレークラインコード内で動作しません(しかし、コンストラクタセクションの作品で...)

+0

ポスト – Wojtek

+0

の最後に追加がまだ動作しません。 TTimerにIntervalを追加する場合にのみ動作します。そして、この値は適切です。 Designtimeで作成した後、ランタイムが再度作成されているようですが、工場設定では、値はfmxファイル(または同様のもの)からマップされます。 – Wojtek

答えて

2

あなたが何を記述するのが正常な動作です。 TPositionのサブプロパティはnodefaultと定義されているため、値に関係なく常にFMXファイルに格納されます。あなたのコンストラクタは設計時と実行時に呼び出されるため、デフォルト値を最初に設定する必要があります。設計時に既存のフォーム/フレームを開くとき、またはプロジェクトを実行時に実行するときには、FMXがロードされてデフォルトを上書きします。完全に正常な動作。FMXファイルの読み込み時にコンポーネントがデフォルト値で動作しないようにするには、ComponentStateプロパティをチェックし、仮想Loaded()メソッドをオーバーライドする必要があります。

BtnPosition.X(またはY)への割り当てを有効にするには、イベントハンドラをTPosition.OnChangeイベントに割り当てる必要があります。

はこれを試してみてください:

unit Layout1; 

interface 

uses 
    System.SysUtils, System.Classes, FMX.Types, FMX.Controls, FMX.Layouts, 
    FMX.StdCtrls, System.Types; 

type 
    TLayout1 = class(TLayout) 
    private 
    { Private declarations } 
    FBtn: TButton; 
    FPosition: TPosition; 

    procedure FPositionChanged(Sender: TObject); 
    procedure FPositionSet(Value: TPosition); 
    protected 
    { Protected declarations } 
    procedure Loaded; override; 
    procedure Notification(AComponent: TComponent; Operation: TOperation); override; 
    public 
    { Public declarations } 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
    published 
    { Published declarations } 
    property BtnPosition: TPosition read FPosition write FPositionSet; 
    end; 

procedure Register; 

implementation 

constructor TLayout1.Create(AOwner: TComponent); 
var 
    PointF: TPointF; 
begin 
    inherited Create(AOwner); 
    FBtn := TButton.Create(Self); 
    FBtn.Parent := Self; 
    FBtn.Stored := False; 
    FBtn.Text := 'Text'; 

    PointF.X := 10; 
    PointF.Y := 10; 
    FPosition := TPosition.Create(PointF); 
    FPosition.OnChange := FPositionChanged; 

    If not (csLoading in ComponentState) then 
    FBtn.Position.Assign(FPosition); 
end; 

destructor TLayout1.Destroy; 
begin 
    FPosition.Free; 
    FBtn.Free;  
    inherited; 
end; 

procedure TLayout1.FPositionChanged(Sender: TObject); 
begin 
    if (FBtn <> nil) and not (csLoading in ComponentState) then 
    FBtn.Position.Assign(FPosition); 
end; 

procedure TLayout1.FPositionSet(Value: TPosition); 
begin 
    if Value <> FPosition then 
    FPosition.Assign(Value); 
end; 

procedure TLayout1.Loaded; 
begin 
    inherited; 
    FBtn.Position.Assign(FPosition); 
end; 

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

procedure Register; 
begin 
    RegisterComponents('Samples', [TLayout1]); 
end; 

end. 
+0

こんにちはレミー、この解決に感謝します。これは、Layout11.BtnPosition.X:= 50問題のみを使用して解決しますが、これだけです。私はまだトップに記載された問題があります - プログラムを起動するときのプロパティ値が "コンストラクタ"のモードにあり、その後プロパティが(Object Inspectorから取得した)値を取得します。 – Wojtek

+0

@Wojtek:これは完全に正常な動作です。私は私の答えを更新しました。 –

+0

非常に良い - それは役に立ちます!さらにもう1つの質問:設計時にBtnの位置を強制的に更新する方法は?プロパティインスペクタを変更するときに同じ場所に表示されます。オブジェクトインスペクタ – Wojtek

関連する問題