从TPanel,Firemonkey版删除按钮

问题描述 投票:0回答:1

使用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
delphi firemonkey
1个回答
0
投票

您的代码存在的问题是您正在删除当前正在运行操作的按钮。当操作返回时,该按钮不再存在,在Windows上,该按钮已由DisposeOf()释放,在移动平台上,该按钮处于“僵尸”状态。

解决方法是将按钮的删除延迟到操作结束为止。在标准Windows应用程序中,我会向自己发布一条消息,以确保操作在我收到消息之前可以结束并可以调用CreateNavPanelButtons()。但是我不确定是否可以在所有其他平台上使用。

以下内容适用于任何平台。

添加TTimerEnabled = FalseInterval = 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;
© www.soinside.com 2019 - 2024. All rights reserved.