使用Delphi 10.2(在Windows 10“ 19H2”下),我可以创建一个新应用,在其上放置一个面板,并创建包含两个项目的动作列表。两项都调用相同的例程,其目的是删除面板上的所有按钮,然后在以下位置添加新的按钮:
procedure TForm1.CreateNavPanelButtons(Action: TAction);
begin
NavPanel.RemoveObject(Btn);
Btn.DisposeOf; //problem line
Btn := MakeButton(Action);
NavPanel.AddObject(Btn);
end;
((我简化为仅在此处使用一个按钮。)删除现有按钮,然后添加新按钮。如果我调用DisposeOf(以释放按钮的内存),则Window对象将无响应(无法调整大小,移动,关闭),直到我将焦点从应用移开。
我在下面包含了完整的代码:
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.StdCtrls,
FMX.Controls.Presentation, System.Actions, FMX.ActnList;
type
TForm1 = class(TForm)
NavPanel: TPanel;
ActionList: TActionList;
acNextMenu: TAction;
acBackToMainMenu: TAction;
procedure FormCreate(Sender: TObject);
procedure acNextMenuExecute(Sender: TObject);
private
{ Private declarations }
public
Btn: TButton;
procedure CreateNavPanelButtons(Action: TAction);
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
function MakeButton(A: TAction): TButton;
begin
Result := TButton.Create(nil);
Result.Action := A;
Result.Text := (A as TAction).Text;
end;
procedure TForm1.acNextMenuExecute(Sender: TObject);
begin
CreateNavPanelButtons(acBackToMainMenu);
end;
procedure TForm1.CreateNavPanelButtons(Action: TAction);
begin
NavPanel.RemoveObject(Btn);
Btn.DisposeOf;
Btn := MakeButton(Action);
NavPanel.AddObject(Btn);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CreateNavPanelButtons(acNextMenu);
end;
end.
这里是表格:
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 NavPanel: TPanel
Align = Top
Size.Width = 640.000000000000000000
Size.Height = 73.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
end
object ActionList: TActionList
Left = 392
Top = 192
object acNextMenu: TAction
Category = 'Navigation'
Text = 'NextMenu'
OnExecute = acNextMenuExecute
end
object acBackToMainMenu: TAction
Category = 'Navigation'
Text = 'Back To &Main Menu'
OnExecute = FormCreate
end
end
end
您的代码存在的问题是您正在删除当前正在运行操作的按钮。当操作返回时,该按钮不再存在,在Windows上,该按钮已由DisposeOf()
释放,在移动平台上,该按钮处于“僵尸”状态。
解决方法是将按钮的删除延迟到操作结束为止。在标准Windows应用程序中,我会向自己发布一条消息,以确保操作在我收到消息之前可以结束并可以调用CreateNavPanelButtons()
。但是我不确定是否可以在所有其他平台上使用。
以下内容适用于任何平台。
添加TTimer
,Enabled = False
,Interval = 1
。然后声明格式为Action: TAction
的私有字段。
更改像这样更改NavPanelButtons
的所有动作处理程序:
procedure TForm2.acNextMenuExecute(Sender: TObject);
begin
// CreateNavPanelButtons(acBackToMainMenu);
Action := acBackToMainMenu;
Timer1.Enabled := True;
end;
并添加OnTimer
事件
procedure TForm2.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
if Action <> nil then
CreateNavPanelButtons(Action);
end;