Delphi7下面关于动态创建控件和释放的个人总结

昨天,一个网友在动态创建控件时释放出了错。他的情况是,动态创建了N个Panel,然后双击Panel就释放掉该Panel。可问题就来了,一释放就出错。然后就一顿讨论。当然也有其他的高手给出了代码,可高手的代码用的是XE5写的。我和那位网友都是Delphi7。网上也有别的一些动态创建和释放控件的代码但是跟我这讲的不一样。现在就把我自己在这件事的一些所想写下来,为后面的一些人提示或者铺路。软件这玩意跟环境有很大的关系。我先说说本次所用的编程环境Delphi7+XP系统。

碰到的问题

我们写东西,当然是有代码来还原当时的情形:首先我们通过一个按钮来增加Panel。我们双击一次界面添加一个Panel。下面是代码:版本1

procedure TForm1.Button1Click(Sender: TObject);
begin
      with TPanel.Create(Self) do
    try
      Parent := Self;
      Left := 50+100*Num;//Num是全局变量,这样创建的Panel就不会叠在一起
      Width := 50;
      Top := 50+100*Num;
      Height := 50;
      Color := clRed;
      Caption := IntToStr(Num);
      Tag := Num;
      Name := Format('Panel%d',[Num]);
      OnDblClick := Panel1DblClick;//动态添加Panel的双击事件
 finally
 end;
 Inc(Num);
end;

动态创建了Panel我们还应该给出Panel的双击事件。代码也如下

procedure TForm1.Panel1DblClick(Sender:TObject);
var
 DName:String;
begin
   //DPanel := TPanel(Sender);//1
   //DPanel.Caption := 'Change!';}//2这段代码你可以先留心一下。
   TPanel(Sender).Free;//3                                                                                                                    //Timer1.Enable := True;//4
end;

问题就来了,双击运行时你会发现D7+XP环境下会有好几种问题:第1中:任何一个Panel你都无法释放,运行时弹窗出错。当然情况跟电脑操作系统和Delphi7的版本可能有关。

然后就是我在考虑是不是因为不能自己杀自己呢。于是我自己就做了修改,上面的代码注释掉了3,保留了1.2,4然后添加了一个Timer组件,设置时间为1,然后再Timer事件中我在进行释放Panel空间的操作:版本2

procedure TForm1.Timer1Timer(Sender: TObject);
begin

    DPanel.Free();
    Timer1.Enabled := False;

end;

这样就没有问题了,而且你会发现你双击的Panel空间的字改成了Change。这就说明Sender进行“赋值”其实是赋址。我一开始欣欣然以为找到了问题的根源,可是后来我又到网上看了一下别的版本就是我定义一个全局变量的名字叫BiPanel的Panel数组,然后我创建的Panel都保存在这。最后释放的时候更据TPanel(Sender).Tag的值来销毁Panel。这就是版本3:

procedure TForm1.Panel1DblClick(Sender:TObject);
var
 DPanel:Integer;
begin

   DPanel := TPanel(Sender).Tag;
   BiPanel[DPanel].Free();
end; 

我运行完之后发现这样也可以,就是不算动态生成Panel,因为这样生成的Panel是有限的。然后我把这段代码还原回去变成了版本1,结果发现最初的版本居然可以用了,就是是成为了第2个情况:你删除Panel要按照他们的顺序来。就是按照Num的顺序来。我表示这样的话,用户体验得多糟啊。那么为什么会是这种情况呢。我个人的猜测你双击事件中有一个参数Sender:TObject。你自己释放自己,也就存在一些潜在的问题。这过程中就释放了Panel,Sender是指向一个内存地址的。拿整个程序为例,系统为我们的程序分配了好几个Panel对象的内存地址空间,但是这些空间共享了同一个双击事件。也就是说我们用Delphi7的时候最好不要再自身内部释放,问题很多的

结论    

  不要再动态生成的控件的共享触发事件中释放控件,这样做很糟糕。                                                                       

猜你喜欢

转载自blog.csdn.net/www1157763637qqcom/article/details/17841819