【问题标题】:Inaccessible value from control on embedded child form (Delphi, Firemonkey)嵌入式子窗体(Delphi、Firemonkey)上的控件无法访问值
【发布时间】:2020-03-16 08:54:42
【问题描述】:

我是 Firemonkey 的新手(使用 RadStudio 10.3.2),我正在尝试更新嵌入式子窗体上的列表框控件。但是,当我尝试访问列表框 (ListBox1) 的任何属性时,它们会显示为“无法访问的值”。我很确定我错过了一些非常简单的东西。我感谢任何和所有的帮助!谢谢!

我做了以下简化的应用程序来说明我的问题。

Project1 应用程序初始化:

program Project1;

uses
  System.StartUpCopy,
  FMX.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Unit1.pas:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure EmbedForm(AParent:TControl; AForm:TCustomForm);
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses Unit2;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Embed Scenarios Form
  EmbedForm(Panel1, TForm2.Create(Self));
  Panel1.Visible := true;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  data_strings: array of string;
begin
  // Assign strings
  SetLength(data_strings, 2);
  data_strings[0] := 'Hello';
  data_strings[1] := 'World';
  // Load strings
  Form2.ListBox1.Items.Add(data_strings[0]);
  Form2.ListBox1.Items.Add(data_strings[1]);
end;

procedure TForm1.EmbedForm(AParent: TControl; AForm: TCustomForm);
begin
  while AForm.ChildrenCount>0 do
    AForm.Children[0].Parent:=AParent;
end;

end.

Unit2.pas:

unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts,
  FMX.ListBox;

type
  TForm2 = class(TForm)
    ListBox1: TListBox;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

end.

Form2.ListBox1 属性对于主窗体上的代码是不可访问的——请参见 Button1Click 事件。我有使用子表单(Unit2)的父表单(Unit1)。

我不知道为什么无法访问已启用的可见组件。我的模态表单从来没有遇到过这个问题,所以我认为这与嵌入的子表单有关。

【问题讨论】:

  • 更新了代码以显示应用程序初始化和 fMain 初始化。
  • 感谢您的编辑。请阅读minimal reproducible example。现在主窗体中有大量不相关的字段。但无论如何,我设法弄清楚以前的代码大概是如何声明的,但我无法重现你的问题。例如,您声称 fScenarios.lb_Scenarios.Items.Add(data[i]) 将无法访问,但在这里可以访问。我猜你除了lb_Scenarios: TListBox; 之外没有在嵌入式表单中声明任何其他内容(与问题相关),那是在已发布部分,对吧?
  • @Tom - 正确。我现在已经上传了所有代码,减去了不相关的控件。主窗体识别 fScenarios.lb_Scenarios.Items.Add,但是当代码在调试中运行时,获取任何 fScenarios.lb_Scenarios 属性都会导致无法访问值消息。我想知道我如何创建 fScenario 表单并将其绑定到主表单上的面板 (p_Scenarios) 是否存在问题。失败的代码在 bScenarioClick 事件中,在 cmets 中已经注明。
  • @Tom - 我已经上传了新代码来复制我的问题,没有任何无关的材料。这在 Form1 上使用 Unit1.pas、Unit2.pas、Button1 和 Panel1,在 Form2 上使用 ListBox1。

标签: delphi firemonkey rad-studio


【解决方案1】:

错误在于您没有保留对TForm2 实例的引用。然而,您稍后在程序中尝试使用全局 Form2 变量。

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Embed Scenarios Form
  EmbedForm(Panel1, TForm2.Create(Self)); 
  Panel1.Visible := true;
end;

TForm2.Create(self) 返回一个引用,您将其传递给EmbedForm() 但后来你失去了它。 稍后在 Button1.Click 中调用 Form2.ListBox1.Items.Add(data_strings[0]); 但未分配 Form2

将其更改为例如:

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Embed Scenarios Form
  Form2 := TForm2.Create(Application); // Use `Form2` name declared in `Unit2`
  EmbedForm(Panel1, Form2);
  Panel1.Visible := true;
end;

【讨论】:

  • 谢谢你,汤姆!!!这就是问题所在!该示例现在运行良好!
  • @Ric 欢迎您。正是这个简化的示例让我们更容易发现实际问题。
【解决方案2】:

你改变了“父母”,但“所有者”没有改变

fmain.lb_Scenarios.Items.Add(data[i])

【讨论】:

  • 这会产生一个错误,指出“TfMain 不包含名为 lb_Scenarios 的成员。”列表框 lb_Scenarios 位于子窗体 (fScenarios) 上。子窗体嵌入在主窗体的 (fMain) 面板 (p_Scenarios) 中。我希望这有帮助!谢谢!
猜你喜欢
  • 2020-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 2021-04-12
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
相关资源
最近更新 更多