无法更改 Delphi 中的 TEdit 文本

Cannot change TEdit Text in Delphi

我在 运行 时将组件添加到表单,我还在字典中添加更改这些组件属性的事件,以便稍后调用它们。

TEventBeforeInsert = function(var AComponent: TComponent; AForm: TForm): Boolean of Object;

TFieldBase = class
private
  FEvent:TEventBeforeInsert;
....
function TFieldBase.EventBeforeInsert: TEventBeforeInsert;
begin
  Result:=FEvent;
end;

function TFieldBase.EventBeforeInsert(AEvent: TEventBeforeInsert): TFieldBase ;
begin
  FEvent:=AEvent;
  Result:=Self;
end;

....

表单调用

TFormBase.New
.addStringField
(
    TFieldBase.New
    .Enabled(True)
    .Description('User')
    .EventBeforeInsert(TEvents.New.EditFillUser), TTabsNames.Tab1
).Show();

表格Class

TFormBase = class(TForm)
private
FDictionary: TDictionary<String, TEventBeforeInsert>;
...
function TFormBase.addStringField(AField: TFieldBase; ATab: TTabsNames): TFormBase;
var
  FLink: TLinkControlToField;
  FEdit: TEdit;
begin
  Result := Self;
  FEdit := TEdit.Create(Self);
  FEdit.Visible := True;
  FEdit.Parent := TPanel(PanelParent.FindComponent('PanelTab' + Ord(ATab).ToString));
  FEdit.Enabled:=AField.Enabled;

 
  if Assigned(AField.EventBeforeInsert) then
  begin
    FDictionary.Add(FEdit.Name,AField.EventBeforeInsert);
  end;
end;
...
procedure TFormBase.rectInsertClick(Sender: TObject);
var
    Item:String;
begin
  for Item in FDictionary.Keys do
  begin
    if Not FDictionary.Items[Item](Self.FindComponent(Item),Self) then
      Exit;
  end;
end;

我在这里遇到问题,在调试时我看到文本 属性 被正确更改,但显示的表单没有任何更改。

TEvents = class
...
function TEvents.EditFillUser(AComponent: TComponent;AForm: TForm): Boolean;
begin
  TEdit(AComponent).Text:=IntToStr(0);
  Result:=True;
end

我认为变量按值传递可能是个问题...有人可以帮我吗?

编辑 1: 我试过这样声明的字典:

FDictionary: TDictionary<TComponent, TEventBeforeInsert>;
...
if Not FDictionary.Items[Item](Item,Self) then //call

我也试过像这样使用 TForm 参考:

function TEvents.EditFillUser(AComponent: String;AForm: TForm): Boolean;
begin
  TEdit(AForm.FindComponent(AComponent)).Text:=IntToStr(0);
  Result:=True;
end

TFormBase.addStringField() 中,在将新创建的 TEdit 对象插入 FDictionary. 之前,您没有为其分配 Name 值。只有在 design-time 创建的组件有 auto-generated Name。在 run-time 创建的组件没有。因此,您正在使用空白 Name 跟踪您的对象。如果你想通过Name来跟踪对象,你需要实际将自己的值赋给FEdit.Name,例如:

function TFormBase.addStringField(AField: TFieldBase; ATab: TTabsNames): TFormBase;
var
  ...
  FEdit: TEdit;
  FEvent: TEventBeforeInsert;
begin
  ...
  FEdit := TEdit.Create(Self);
  FEdit.Name := 'SomeUniqueNameHere'; // <-- for you to decide on...
  ...
 
  FEvent := AField.EventBeforeInsert;
  if Assigned(FEvent) then
    FDictionary.Add(FEdit.Name, FEvent);
end;

但是,在这种特殊情况下,我认为根本没有理由使用 TDictionary。考虑改用 TList,这样就根本不需要 Name。这也将提高 TFormBase.rectInsertClick() 中迭代的性能,因为它不必再使用 FindComponent() 寻找每个 TComponent 对象:

TFormBase = class(TForm)
private
  type TEventBeforeInsertPair = TPair<TComponent, TEventBeforeInsert>;
  FBeforeInsertEvents: TList<TEventBeforeInsertPair>;
  ...
public
  constructor Create;
  destructor Destroy; override;
  ...
end;

...

constructor TFormBase.Create;
begin
  inherited;
  FBeforeInsertEvents := TList<TEventBeforeInsertPair>.Create;
end;

destructor TFormBase.Destroy;
begin
  FBeforeInsertEvents.Free;
  inherited;
end;

function TFormBase.addStringField(AField: TFieldBase; ATab: TTabsNames): TFormBase;
var
  ...
  FEdit: TEdit;
  FEvent: TEventBeforeInsert;
begin
  ...
  FEdit := TEdit.Create(Self);
  ...

  FEvent := AField.EventBeforeInsert;
  if Assigned(FEvent) then
    FBeforeInsertEvents.Add(TEventBeforeInsertPair.Create(FEdit, FEvent));
end;

procedure TFormBase.rectInsertClick(Sender: TObject);
var
  Item: TEventBeforeInsertPair;
begin
  for Item in FBeforeInsertEvents do
  begin
    if not Item.Value(Item.Key, Self) then
      Exit;
  end;
end;

...

此外,您的 TEvents.EditFillUser() 方法与 TEventBeforeInsert 的定义不匹配。 TEventBeforeInsert 的第一个参数被声明为通过 var 引用传递 TComponent 指针(为什么?),但 EditFillUser() 的第一个参数没有这样做。除非您希望您的事件处理程序更改 TComponent 指针指向的内容(这不会像您当前使用 TEventBeforeInsertTDictionary 的方式那样工作),否则没有理由完全通过 var 引用传递 TComponent 指针:

TEventBeforeInsert = function(AComponent: TComponent; AForm: TForm): Boolean of Object;

此外,您对 TEvents.New 的使用似乎是内存泄漏,因为没有人取得新创建的 TEvents 对象的所有权(除非其构造函数将该对象添加到某个内部列表中我们看不到)。与 TFieldBase.New 相同。甚至 TFormBase.New(假设没有 OnClose 事件在关闭表单时设置 Action=caFree)。在某些时候,您需要调用 Free()Create().

的任何 class 对象