Control on embedded form not refreshing (Delphi, Firemonkey)

  

I have a very simple Firemonkey project (RadStudio 10.3.3) that I am building to test certain layout options for a future project. In the past with VCL, I used modal forms. The project I am testing uses panels (Panel1 and Panel2) on the main form (Form1) to embed two additional forms (Form2 and Form3). The two embedded forms consist of a single listbox (ListBox1) on each form. The panels on the main form overlay, so I use the Visibility property to show the embedded form that I want. All the code is on the main form.

The issue I have is that when I switch between Form2 and Form3, the strings loaded into the listbox on Form3 never appear. I have tried Repaint on the listbox and panel, InvalidateRect on the listbox, SetFocus on the panel, etc., all followed by Application.ProcessMessages. Nothing works successfully.

The main code is:

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 is as follows:

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 is as follows:

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.

The .fmx files are below, as requested.

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

Again, Form2 and Form3 each only contain a listbox (Listbox1 on both) and no additional code. I simply run the executable, click Button1 to display Hello World, then click Button2 to switch panels and display the second form and its listbox. As I am new to Firemonkey, I am sure I am missing something simple. Thanks for any and all help!

The solution was very simple. I had to remove the CreateForm events for Form2 and Form3 from the project’s initialization settings–a dumb mistake on my part. It was losing the reference to those forms during execution.

Comments are closed.