3

現在、ボタンをクリックすると、新しいフォームにいくつかの図形が作成されます。新しいフォームを閉じたら、どのようにしてそれが作った形を破壊することができますか。

必要に応じてさらに情報を追加できますが、フォームが閉じたときにすべてのTMachineインスタンスを破棄する簡単な方法があることを望んでいました。

TMachineTShapeクラスです

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クラス

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.
4

2 に答える 2

5

示されているコードはVCL所有権モデルを利用しており、フォームを作成するときにコンポーネントの所有者としてフォーム自体を渡すだけなので、フォームはそれを解放します。

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

これはTFLayout1クラスから呼び出されるため、フォームの特定のインスタンスがそれ自体を破棄している場合、所有されているすべてのコンポーネントが解放されます。

もう少し詳しくは、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アプリケーションの舞台裏で何が起こっているのかを理解するには、ドキュメントと参照記事を読む必要があります。

于 2013-01-28T05:44:53.993 に答える
3

オブジェクトにを割り当ててOwnerいますTMachineOwnerシェイプ自体が解放されると、シェイプは自動的に解放されます。

FormTFLayout1クラスであるとすると、デフォルトでは、閉じたときに自動的に解放されません。閉じたフォームはデフォルトで非表示になっているため、必要に応じて再表示できます。クローズ時に実際に解放するには、イベントのActionパラメーターをに設定するか、フォームが閉じられた直後に呼び出す必要があります(たとえば、でフォームを表示している場合は、終了後に呼び出すことができます)。TForm.OnClosecaFreeTForm.Free()ShowModal()Free()ShowModal()

の動作に依存せずに自分で図形を解放する場合は、図形を作成するときにをに設定Ownerし、各図形を解放する必要があるときにループできるようにポインタを格納するか、プロパティを設定して必要なときにできることを真実に。フォームのイベントなど。OwnernilTMachineTListTObjectListOwnsObjectsClear()OnClose

于 2013-01-28T05:47:36.470 に答える