目前,当我点击一个按钮时,它会在新表格上创建一些形状。一旦我关闭新表格,我怎么能破坏它所形成的形状。
如果需要,我可以添加更多信息,但希望有一种简单的方法可以在表单关闭时销毁所有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;
TMachine Class
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.
答案 0 :(得分:5)
显示的代码正在利用VCL ownership model,表单会为您释放它,因为您在创建表单时只需将表单作为组件的所有者传递:
machine := MachineShape.TMachine.Create(self);
因为这是从TFLayout1类调用的,当表单的特定实例正在自行销毁时,它将释放所有拥有的组件。
如需了解更多信息,请阅读文章:Owner vs. Parent in Delphi。
通过评论,您可以在与您显示的表单不同的类上创建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应用程序中幕后发生的事情。
答案 1 :(得分:3)
您正在为Owner
个对象分配TMachine
。当Owner
本身被释放时,形状将自动释放。
假设TFLayout1
是您的Form类,那么默认情况下它不会在关闭时自动释放。默认情况下隐藏已关闭的表单,以便您可以在需要时重新显示。要在关闭时实际释放它,您必须将Action
事件中的TForm.OnClose
参数设置为caFree
,或者在表单关闭后的某个时间直接调用TForm.Free()
(例如好像您正在使用ShowModal()
显示表单,然后您可以在Free()
退出后致电ShowModal()
。
如果您想在不依赖Owner
行为的情况下自行释放形状,请在创建形状时将Owner
设置为nil
,然后存储{{1} TMachine
中的指针,您可以在需要时循环播放每个形状,或者TList
将TObjectList
属性设置为true,以便在需要时OwnsObjects
。例如在Form Clear()
事件中。