【问题标题】:Using Tedit Inside of a FireMonkey component在 FireMonkey 组件中使用 Tedit
【发布时间】:2017-05-10 08:16:36
【问题描述】:

我在 Fire-monkey 中创建了一个组件,并在其中创建了一个 TEdit。 我的组件有一个名为 Value 的字符串属性,通过向它添加任何字符串,我的组件将在 Tedit 中显示它。 在设计时,一切正常。但在运行时,Tedit 中没有显示任何内容 我的代码是

type
TMyComponent = class(TPanel)
private
  { Private declarations }
  Edit:TEdit;
  FValue:String;
  Procedure SetValue(Const Value:String);
protected
  { Protected declarations }
  Constructor Create(Aoner:TComponent); Override;
  Destructor Destroy; Override;
public
  { Public declarations }
published
  { Published declarations }
  Property Value:String Read FValue Write SetValue;
end;

procedure Register;

implementation

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

Constructor TMyComponent.Create(Aoner:TComponent);
begin
  Inherited;
  Width:=100;
  Height:=100;
  Edit:=TEdit.Create(Self);
  Edit.Parent:=Self;
  Edit.Width:=30;
  Edit.Text:='';
  Edit.Align:=TAlignLayout.Scale;
end;

Procedure TMyComponent.SetValue(const Value: string);
begin
  FValue:=Value;
  Edit.Text:=FValue;
end;

Destructor TMyComponent.Destroy;
begin
  Edit.Destroy;
  Inherited Destroy;
end;
end.

我该怎么办?

【问题讨论】:

  • 您在运行时测试的代码在哪里?
  • 看加载的
  • 我无法重现您在运行时遇到的任何问题。请尝试通过更好的解释来改进您的问题,并将任何缺失的代码添加到您的问题中。
  • 我认为运行时他的意思是,如果您将此组件和按钮放在表单上并在按钮单击事件中写入 MyComponent1.Value := 'test' 组件中的值不会改变。

标签: delphi firemonkey custom-component


【解决方案1】:

您应该使用 FireMonkey 中的样式来执行此类操作,因此对于您的示例,您需要 MyComponent.style 文件,如下所示

object TRectangle
  StyleName = 'MyComponentStyle'
  Align = Center
  Fill.Color = xFFF0F0F0
  HitTest = False
  Size.Width = 159.000000000000000000
  Size.Height = 131.000000000000000000
  Size.PlatformDefault = False
  Stroke.Color = xFFCCCCCC
  object TEdit
    StyleName = 'MyComponentEditStyle'
    Touch.InteractiveGestures = [LongTap, DoubleTap]
    Align = Scale
    TabOrder = 0
    Size.Width = 79.499755859375000000
    Size.Height = 21.833337783813480000
    Size.PlatformDefault = False
  end
end

那么您需要在项目文件中包含MyComponent.rc,如下所示

MyComponentStyle RCDATA  "MyComponent.style"

您的MyComponent.pas 将是

unit MyComponent;

interface

uses System.Classes, FMX.Types, FMX.Controls, FMX.StdCtrls, FMX.Edit, FMX.Styles;

type
  TMyComponent = class(TPanel)
  private
    { Private declarations }
    FEdit: TEdit;
    FValue: string;
    procedure SetValue(const AValue: string);
    function GetValue: string;
  protected
    { Protected declarations }
    procedure FreeStyle; override;
    procedure ApplyStyle; override;
    function GetStyleObject: TFmxObject; override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
  published
    { Published declarations }
    property Value: string read GetValue write SetValue;
  end;

procedure Register;

implementation

uses Winapi.Windows;

{$R MyComponent.res}

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

procedure TMyComponent.ApplyStyle;
begin
  inherited;
  if FindStyleResource<TEdit>('MyComponentEditStyle', FEdit) then
  begin
    FEdit.Visible := True;
    FEdit.Text := Value;
  end;
end;

function TMyComponent.GetStyleObject: TFmxObject;
const
  Style = 'MyComponentStyle';
begin
  if (StyleLookup = '') then
    Result := TStyleStreaming.LoadFromResource(HInstance, Style, RT_RCDATA)
  else
    Result := inherited GetStyleObject;
end;

procedure TMyComponent.FreeStyle;
begin
  FEdit := nil;
  inherited;
end;

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited;
  Width := 100;
  Height := 100;
end;

procedure TMyComponent.SetValue(const AValue: string);
begin
  FValue := AValue;
  if Assigned(FEdit) then
  begin
    FEdit.Text := FValue;
  end;
end;

function TMyComponent.GetValue: string;
begin
  Result := FValue;
end;

end.

【讨论】:

    【解决方案2】:

    最初我认为您在运行时创建和使用组件时遇到了问题。在运行时实例化和使用你的组件完全没问题。

    在 EugeneK 发表评论后,我现在了解到该组件不起作用,如果您在设计时实例化它并尝试在运行时更改 TEdit 的 text 属性。

    原因可以追溯到您的组件是组合类型并且由子组件构造的事实(嗯,只有TEdit)。如果子组件的Stored 属性未设置为False,它们可能会在设计时多次流式传输,例如。当您在表单的表单视图和文本视图之间切换时。

    查看documentation 并向下滚动到TCalender:构造复杂性,您可以在其中找到以下内容:

    组件树中的每个对象都将其 Stored 属性设置为 False 并将其 Locked 属性设置为 True。禁用存储防止 对象通过表单流式传输到 .fmx 文件 设计师。如果未禁用 Stored 属性,子组件将 加载时被冗余创建。

    两次将表单视图切换到文本视图后的结果:

      object MyComponent1: TMyComponent
        Position.X = 8.000000000000000000
        Position.Y = 8.000000000000000000
        Size.Width = 100.000000000000000000
        Size.Height = 100.000000000000000000
        Size.PlatformDefault = False
        TabOrder = 5
        object TEdit
          Touch.InteractiveGestures = [LongTap, DoubleTap]
          Align = Scale
          TabOrder = 1
          Size.Width = 90.000000000000000000
          Size.Height = 18.333332061767580000
          Size.PlatformDefault = False
        end
        object TEdit
          Touch.InteractiveGestures = [LongTap, DoubleTap]
          Align = Scale
          TabOrder = 0
          Size.Width = 90.000000000000000000
          Size.Height = 18.333332061767580000
          Size.PlatformDefault = False
        end
      end
    

    虽然它应该是这样的:

      object MyComponent1: TMyComponent
        Position.X = 8.000000000000000000
        Position.Y = 8.000000000000000000
        Size.Width = 100.000000000000000000
        Size.Height = 100.000000000000000000
        Size.PlatformDefault = False
        TabOrder = 5
      end
    

    多余的TEdit 控件将覆盖您在构造函数中创建的那个。

    对代码的更正: 添加标记线

    constructor TMyComponent.Create(Aoner: TComponent);
    begin
      inherited;
      Width:=100;
      Height:=100;
      Edit:=TEdit.Create(Self);
      Edit.Parent:=Self;
      Edit.Width:=90;
      Edit.Align:=TAlignLayout.Scale;
      Edit.Stored := False;  // *** add this line ***
    end;
    

    【讨论】:

      猜你喜欢
      • 2014-09-28
      • 2016-07-28
      • 2013-09-15
      • 2021-05-07
      • 2014-09-10
      • 1970-01-01
      • 2015-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多