【问题标题】:Destroy shapes on form close销毁表单关闭的形状
【发布时间】:2013-01-28 05:38:42
【问题描述】:

目前,当我单击一个按钮时,它会在新表单上创建一些形状。一旦我关闭了新表格,我该如何破坏它制作的形状。

如果需要,我可以添加更多信息,但希望有一种简单的方法可以在表单关闭时销毁所有 TMachine 实例。

TMachine 是一个 TShape 类

procedure TFLayout1.GetClick(Sender: TObject);
var
  azone: string;
  adept: string;
  machine : TMachine;
begin
  fdb.count := 0;  //keeps track of number of machines in zone
  azone := MyDataModule.fDB.GetZone(Name);    //gets name of zone
  adept := TButton(Sender).Name;       //gets name of dept
  fdeptlayout.ListBox1.Clear;

  fdeptlayout.show;
  with fdeptlayout.ADOQuery1 do
    begin
         sql.Clear;
         sql.BeginUpdate;
         sql.Add('SELECT');
         sql.Add(' *');
         sql.Add('FROM');
         sql.Add(' `MList`');
         sql.Add('WHERE `Zone` = :myzone ');
         sql.Add(' AND `Dept` = :mydept');
         sql.EndUpdate;

         parameters.ParamByName('myzone').Value := azone;
         parameters.ParamByName('mydept').Value := adept;
         open;
    end;

  //gets number of machines in total
  while not fdeptlayout.ADOQuery1.Eof do
    begin
      fdb.count := fdb.count+1;
      fdeptlayout.ADOQuery1.Next;
    end;

  //restarts back at first query
  fdeptlayout.ADOQuery1.First;

   //clears the last x value
   fdb.LastX :=0;

  //creates the shape
  while not fdeptlayout.ADOQuery1.Eof do
    begin
        machine := MachineShape.TMachine.Create(self);
        machine.Parent := fdeptlayout;
        machine.PlaceShape(44,44,'CM402','first','123/33/123');
        fdeptlayout.ListBox1.Items.Add(fdeptlayout.ADOQuery1.FieldByName('Name').AsString);
        fdeptlayout.ADOQuery1.Next;
    end;
end;

TMMachine 类

unit MachineShape;


interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, extctrls,myDataModule,Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type

TMachine = class(TShape)
  private
    { Private declarations }
  public
    { Public declarations }
    procedure PlaceShape(sizeW,sizeH :integer; name, order,asset : string);
  end;
implementation



    Procedure TMachine.PlaceShape(sizeW,sizeH :integer; name, order,asset : string);
    begin
       self.width :=  sizeW;
       self.height := sizeH;
       self.top := 136;
       self.left := MyDataModule.fDB.LastX +2;//set left
       MyDataModule.fDB.lastx := left + sizeW;
       showmessage(inttostr(mydatamodule.fDB.LastX));
    end;

end.

FDeptLayout

unit DeptLayout;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls,mydatamodule, Vcl.Forms, Vcl.Dialogs, Data.DB, Data.Win.ADODB, Vcl.StdCtrls,
  Vcl.ExtCtrls;

type
  TfDeptLayout = class(TForm)
    ADOQuery1: TADOQuery;
    ListBox1: TListBox;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  fDeptLayout: TfDeptLayout;

implementation

{$R *.dfm}

procedure TfDeptLayout.FormClose(Sender: TObject; var Action: TCloseAction);
begin

end;

end.

【问题讨论】:

    标签: delphi delphi-xe2


    【解决方案1】:

    显示的代码利用了VCL ownership model,表单将为您释放它,因为您只需在创建表单时将表单本身作为组件的所有者传递:

    machine := MachineShape.TMachine.Create(self);
    

    因为这是从 TFLayout1 类调用的,所以当表单的特定实例正在销毁自身时,它将释放所有拥有的组件。

    更多信息,您可以阅读文章:Owner vs. Parent in Delphi

    编辑

    从 cmets,它导致您在与显示它的表单不同的类上创建 TMachine 实例,并且在关闭它时不会破坏表单实例,因此,您可以达到您想要的进行此更改:

    • 将显示形状的表单设为所有者,将创建它们的代码更改为:

      //don't use self, now the parent is the instance referenced by fdeptlayout
      machine := MachineShape.TMachine.Create(fdeptlayout);
      
    • 在您的 Tfdeptlayout 类中,使用以下代码添加 OnClose 处理程序:

      begin
        for I := ComponentCount - 1 downto 0 do
          if Components[I] is TMachine then
            Components[I].Free;
      end;
      

    也就是说,您确实必须阅读文档和参考文章才能对 Delphi 应用程序的幕后情况有所了解。

    【讨论】:

    • 但是如果我关闭新表单(上面有形状)然后再次打开它,形状仍然存在,即使当我第二次打开它时它应该只显示 4 个形状,其中第一个时间显示 13 .. 如果有任何意义
    • 关闭表单时是否销毁? fdeptlayout 变量是哪种类型?什么是 TFLayout1 类?
    • TFLayout 是一个窗体,它正在创建类 TMachine,类 TMachine 显示在另一个窗体 Fdeptlayout 上。 FDeptLayout 是我要关闭的表单。但会在某个时候再次调用该表单。
    • form 如何创建类?你必须注意你用的词,否则很难理解你想说什么。例如,Form(这让我想到了一个运行时对象,也称为实例)不能创建类,而类是用于创建此类对象实例的模具。类只能由程序员在编译应用程序之前在源代码中创建
    • 通过创建类,我的意思是创建实例` machine := MachineShape.TMachine.Create(self);`
    【解决方案2】:

    您正在将 Owner 分配给您的 TMachine 对象。当Owner 本身被释放时,形状将被自动释放。

    假设TFLayout1 是你的Form 类,那么默认情况下它在关闭时不会被自动释放。默认情况下隐藏已关闭的表单,因此您可以在需要时重新显示。要在关闭时真正释放它,您必须将TForm.OnClose 事件中的Action 参数设置为caFree,或者在表单关闭后的某个时间直接调用TForm.Free()(例如,如果您正在使用ShowModal(),那么你可以在ShowModal()退出后调用Free()

    如果您想自己释放形状而不依赖Owner 的行为,则在创建形状时将Owner 设置为nil,并将TMachine 指针存储在TList 中您可以在需要时循环以释放每个形状,或者将 TObjectListOwnsObjects 属性设置为 true ,您可以在需要时使用 Clear()。比如Form的OnClose事件中。

    【讨论】:

    • 我宁愿自己做,所以TMachine 是在TFLayout1 上创建的,但在FDeptLayout 上显示所以在FDeptLayout 结束时我需要......在这个之后迷路了哈哈
    • 如果我在 onclose 期间调用free(),那么如果我再次尝试打开它,表单不再存在,从而给我访问错误。
    猜你喜欢
    • 2013-12-02
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 2017-05-01
    • 2014-03-08
    • 1970-01-01
    • 2021-12-08
    • 2013-06-17
    相关资源
    最近更新 更多