【问题标题】:Control on embedded form not refreshing (Delphi, Firemonkey)嵌入式表单控件不刷新(Delphi、Firemonkey)
【发布时间】:2020-04-02 21:34:51
【问题描述】:

我正在构建一个非常简单的 Firemonkey 项目 (RadStudio 10.3.3),以测试未来项目的某些布局选项。在过去的 VCL 中,我使用了模态形式。我正在测试的项目在主窗体 (Form1) 上使用面板(Panel1 和 Panel2)来嵌入两个附加窗体(Form2 和 Form3)。这两个嵌入的表单由每个表单上的单个列表框 (ListBox1) 组成。主窗体上的面板覆盖,所以我使用 Visibility 属性来显示我想要的嵌入窗体。所有代码都在主窗体上。

我遇到的问题是,当我在 Form2 和 Form3 之间切换时,加载到 Form3 上的列表框中的字符串永远不会出现。我在列表框和面板上尝试过Repaint,在列表框上尝试过InvalidateRect,在面板上尝试过SetFocus 等等,后面都是Application.ProcessMessages。没有什么能成功。

主要代码是:

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;
    Panel2: TPanel;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    procedure EmbedForm(AParent:TControl; AForm:TCustomForm);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses Unit2, Unit3;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Embed Form2 in Panel1
  Application.CreateForm(TForm2, Form2);
  EmbedForm(Panel1, Form2);
  Panel1.Visible := true;

  // Embed Form3 in Panel2
  Application.CreateForm(TForm3, Form3);
  EmbedForm(Panel2, Form3);
  Panel2.Visible := false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Populate ListBox1 on Form2 - the LOAD button
  Form2.ListBox1.Items.Add('Hello');
  Form2.ListBox1.Items.Add('World');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  // Hide Panel1 (Form2) and show Panel2 (Form3)
  Panel1.Visible := false;
  Panel2.Visible := true;
  // Populate ListBox1 on Form3
  Form3.ListBox1.Items.Add('Goodbye');
  Form3.ListBox1.Items.Add('World');
  // Repaint (Here's why I have tried various things to get the listbox strings to show up)
  //Panel2.Repaint;
  //Form3.ListBox1.Repaint;
  //Application.ProcessMessages;
end;

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

end.

Form2如下:

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.

Form3如下:

unit Unit3;

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, FMX.Controls.Presentation, FMX.StdCtrls;

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

var
  Form3: TForm3;

implementation

{$R *.fmx}

end.

.fmx 文件按要求如下。

Unit1.fmx (Form1):

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnCreate = FormCreate
  DesignerMasterStyle = 0
  object Button1: TButton
    Position.X = 232.000000000000000000
    Position.Y = 448.000000000000000000
    TabOrder = 1
    Text = 'Load'
    OnClick = Button1Click
  end
  object Button2: TButton
    Position.X = 328.000000000000000000
    Position.Y = 448.000000000000000000
    TabOrder = 2
    Text = 'Next'
    OnClick = Button2Click
  end
  object Panel1: TPanel
    Align = Center
    Size.Width = 640.000000000000000000
    Size.Height = 393.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 0
  end
  object Panel2: TPanel
    Position.Y = 43.000000000000000000
    Size.Width = 640.000000000000000000
    Size.Height = 393.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 4
  end
end

Unit2.fmx (Form2):

object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object ListBox1: TListBox
    Align = Center
    TabOrder = 0
    DisableFocusEffect = True
    DefaultItemStyles.ItemStyle = ''
    DefaultItemStyles.GroupHeaderStyle = ''
    DefaultItemStyles.GroupFooterStyle = ''
    Viewport.Width = 200.000000000000000000
    Viewport.Height = 200.000000000000000000
  end
end

Unit3.fmx (Form3):

object Form3: TForm3
  Left = 0
  Top = 0
  Caption = 'Form3'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object ListBox1: TListBox
    Position.X = 8.000000000000000000
    Position.Y = 8.000000000000000000
    TabOrder = 1
    DisableFocusEffect = True
    DefaultItemStyles.ItemStyle = ''
    DefaultItemStyles.GroupHeaderStyle = ''
    DefaultItemStyles.GroupFooterStyle = ''
    Viewport.Width = 196.000000000000000000
    Viewport.Height = 196.000000000000000000
  end
end

同样,Form2 和 Form3 都只包含一个列表框(两者都包含 Listbox1)并且没有额外的代码。我只需运行可执行文件,单击 Button1 显示 Hello World,然后单击 Button2 切换面板并显示第二个表单及其列表框。由于我是 Firemonkey 的新手,我确信我缺少一些简单的东西。感谢您的所有帮助!


解决方案非常简单。我不得不从项目的初始化设置中删除 Form2 和 Form3 的 CreateForm 事件——这对我来说是一个愚蠢的错误。它在执行过程中失去了对这些表单的引用。

【问题讨论】:

  • FWIW,将嵌入内容放在源表单上的 TLayout 内要容易得多,然后只需分配该布局的父级。
  • @Jerry 感谢您提供信息。我将开始研究 TLayout 容器。我使用 TPanel 是因为我在 VCL 中熟悉它们。
  • 我现在删除了我的答案,因为你声称不可能是这样。但是,由于从您发布的代码中看不到子父关系,我要求您将三个.fmx 文件添加到您的问题中。我还需要强调,如果面板是Form1 的直接子代,我无法重现您的问题。它只是按照您的预期工作。
  • @Tom - 我已经按照你的要求完成了。如您所见,Unit2 (Form2) 或 Unit3 (Form3) 不涉及任何内容。既然你不能复制问题,我就从头开始构建另一个测试用例,看看问题是否存在。我的主要软件也有这个问题,这就是为什么我构建了简单的测试代码来验证我的问题。正如我所提到的,我刚刚更新到 RadStudio 10.3.3,尽管我在 10.3.2 中遇到了同样的问题。感谢您的所有帮助!
  • 感谢您的更新。但是,现在您在Unit1.fmx 中拥有TPanel,并且作为该面板的孩子,TLayout,您在Unit1.pas 中没有。 Otoh,你在Unit1.fmx 中根本没有Panel2!所以Unit1.fmx 不匹配Unit1.pas。如果您已将第二个面板更改为TLayout(基于 Jerry 的建议),并且该面板位于当前布局的位置,那么这正是我在回答中所说的。 Panel2Panel1 的子代,而不是 Form1 的子代。这正是您描述的行为。你同意吗?

标签: delphi listbox firemonkey rad-studio


【解决方案1】:

我可以重现错误的唯一方法是错误地设置表单和两个面板之间的父子关系。

例如我可以重现您描述的错误行为,如果Panel2Panel1 的孩子,但如果它们都是表单的孩子,我无法重现该问题。也许您错误地将第二个面板放在Panel1 上?检查 IDE 中的结构窗口。


编辑.fmx 文件添加到问题后

查看提供的Unit1.fmx,其结尾如下:

  object Panel1: TPanel
    Align = Center
    Size.Width = 640.000000000000000000
    Size.Height = 393.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 0
    object Layout1: TLayout
      Align = Contents
      Size.Width = 640.000000000000000000
      Size.Height = 393.000000000000000000
      Size.PlatformDefault = False
      TabOrder = 0
    end
  end

根据Unit1.pas 应该没有Panel2。相反,Layout1Panel1 的子代。因此,现在发布的.fmx 文件与您昨天提供的.pas 文件不匹配。但它可能仍然证实了我已经说过的话。

如果 Panel2 已被此布局替换,换句话说,Panel2Panel1 的子级,那么这将准确解释您最初询问的行为。

【讨论】:

  • 我会在早上检查并告诉你!感谢您对此进行调查!
  • 我刚刚查看了我的测试代码(上面发布),两个面板都是 Form1 的子面板。对不起,我忘了我已经把测试代码上传到我的 CM 软件中了。再次感谢您的建议!
  • 抱歉,汤姆!根据 Jerry 的评论,我已经开始使用 TLayout,并且不小心发布了工作代码而不是原始代码。我很抱歉!我已经更新了上面的 .fmx 代码以反映原始的两面板设计!再次道歉!
【解决方案2】:

好的,感谢 Tom 的挫败感(再次,对不起 Tom!)以及我自己的挫败感,我再次重建了测试应用程序。这一次,两个列表框都不会显示字符串。然后我开始考虑 Form2 和 Form3 失去与 Form1 的连接,因此我查看了 Tom 询问的 .fmx 文件。这导致我查看了项目初始化文件,瞧!

program Project1;

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

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  //Application.CreateForm(TForm2, Form2);  <-- NOW COMMENTED OUT
  //Application.CreateForm(TForm3, Form3);  <-- NOW COMMENTED OUT
  Application.Run;
end.

应用程序在启动时创建 Form2 和 Form2,然后我会在代码中创建重复项,从而导致引用丢失。我只是在启动时注释掉了 Form2 和 Form3 行,以防止应用程序创建它们并按预期工作。谢谢,汤姆!

【讨论】:

  • 嗯,这当然可以部分解释问题,但由于Form2 实际上按预期工作,您一定已经在前面评论了第一行。神秘的是错误的方式;)
  • 是的,我在上个月开始编写这个测试应用程序时已经将它注释掉了。前几天在添加Form3的时候,完全忘记注释掉了。你说得对,神秘就是虫子的方式!汤姆,我真的很感谢你在这里的所有帮助!
猜你喜欢
  • 2012-02-21
  • 2020-03-16
  • 2016-12-11
  • 2018-09-09
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
相关资源
最近更新 更多