回 帖 发 新 帖 刷新版面

主题:谁能帮忙看下这个错误是怎么回事

简介:
窗体上有一个panel,有一个button(btn1)。
点击btn1后,在panel中生成10个image,10个speedbutton
speedbutton点击后消失(free掉的),露出底下的image。

问题:
speedbutton点击后,总有一个会报错,而且不同机器上报错的位置不同。
我自己机器上是左起第六个报错,同事机器有的是第六个有的是第五个
另外,本来窗体上有2个edit(没用到的),删除这2个edit后,再测试我的机器上变成第九个报错了。。。



代码如下,最好是直接下载附件看unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    pnlArea: TPanel;
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
    procedure btnallclick(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
var
  buttonArea:TSpeedButton;
  ImgArea:TImage;
  i:integer;
begin
  for i:=1 to 10 do
  begin

    ImgArea:=TImage.create(Form1);
    ImgArea.Parent:=pnlArea;
    ImgArea.Top:=0;
    ImgArea.Left:=23*i;
    ImgArea.Name:='Img'+inttostr(i+1);
    TImage(ImgArea).Picture.LoadFromFile('.\source\1.bmp');
    buttonArea:=TSpeedbutton.create(Form1);
    buttonArea.Parent:=pnlArea;
    buttonArea.Top:=0;
    buttonArea.Left:=23*i;
    buttonArea.Name:='btn'+inttostr(i+1);
    buttonArea.OnClick:=btnallclick;
  end;

end;

procedure TForm1.btnallclick(Sender: TObject);
begin
     // TSpeedButton(sender).Glyph.LoadFromFile('.\source\1.bmp');
     TSpeedButton(Sender).Free;
end;

end.

回复列表 (共12个回复)

沙发

根据你的代码改的,看一下是否合适:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    pnlArea: TPanel;
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMySpeedBtn = class(TSpeedButton)
    public
    procedure Free2(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
var
  ImgArea:TImage;
  i:integer;
begin
  for i:=1 to 10 do
  begin
    ImgArea:=TImage.create(Form1);
    ImgArea.Parent:=pnlArea;
    ImgArea.Top:=0;
    ImgArea.Left:=23*i;
    ImgArea.Name:='Img'+inttostr(i+1);
    TImage(ImgArea).Picture.LoadFromFile('.\source\1.bmp');
    with TMySpeedBtn.Create(Self) do begin
      Parent:=pnlArea;
      Top:=0;
      Left:=23*i;
      //Name:='btn'+inttostr(i+1);//此句有亦可无亦可
      OnClick := Free2;
    end;
  end;
end;

{ TMySpeedBtn }

procedure TMySpeedBtn.Free2(Sender: TObject);
begin
  Self.Free;
end;

end.

板凳

需要指出的是,你的代码中,SpeedButton的OnClick事件的处理过程是TForm1的一个方法-----这样的话,两个“类”的藕合程度太高了..

3 楼

当然,上面说的不是问题的主要原因。原因是什么,我也在晕中.....好象单独把Name的赋值那句注释掉就行了.....

4 楼

我这种写法问题出在哪?
为什么不同机器出错的按钮不一样?
而且每次是固定位置的按钮出错,如果是每按N个按钮出错我还容易理解点。。

5 楼

另外,要注意我代码中使用了无名对象,也就是 with TObject.Create do...这样的用法。你仔细想一下,在一个循环中,反复执行buttonArea:=TSpeedbutton.create(Form1);这句是不是在编程上就是讲不能的?(没Free就Create,幸亏该对象在栈上)

6 楼

我的BTN1是为了测试方便
实际使用的时候这个应该是些在formcreate里的,所以应该不存在未free就create的情况吧

7 楼

放在TForm1.FormCreate里和放在TForm1.Button1.OnClick里是一样的。

这个问题有点复杂,暂时没时间思考了,以后我会关注的。希望大家一起讨论。

先下了。

8 楼

[quote]另外,要注意我代码中使用了无名对象,也就是 with TObject.Create do...这样的用法。你仔细想一下,在一个循环中,反复执行buttonArea:=TSpeedbutton.create(Form1);这句是不是在编程上就是讲不能的?(没Free就Create,幸亏该对象在栈上)[/quote]
首先说明一点~~Delphi里面对象不是在栈上分配的。最明显的是必须先创建对象才能使用。声明一个buttonArea仅仅是一个指针,栈上也就分配了这个指针的内存,至于这个指针指向什么东西就要看那个create了~~

楼主的代码写的的确奇怪,但是也不能说就是错误的(以我现在看来);楼主个猪,等我想想~~~

9 楼

Punk拜我为师吧~~

1:click事件是在Tcontrol里面声明的~~给你看看重要部分的代码
..............
      if PtInRect(ClientRect, SmallPointToPoint(Message.Pos)) then Click;
  end;
  DoMouseUp(Message, mbLeft); 
 看好~~~当执行完Click以后对象还会调用DomouseUP()过程, 而你在click里面就把这个对象释放了。你可以继续跟踪 它会访问FOnMouseUp 这个私有字段,这个是要在对象所在的堆里面占内存的。
2:为什么会报不同的内存地址错误,这个就比较复杂了,完全和内存分配有关,不同的情况就会分配不同的地址~~
总之,在onclick里面释放本身是不对的~~事件并不一定是一个过程的末端。

10 楼

对了 没有给你说如何解决。
非常简单,设置它Visible就行了~~
另外一点 ImgArea:=TImage.create(Form1); 最好写成 ImgArea:=TImage.create(self);  里面也不用担心内存泄露,Tcomponent会自动管理的。

扫雷不是这样做的,应该完全用Tcanvas画出来。那个数字更不是用的图片,Textout画出来的。

我来回复

您尚未登录,请登录后再回复。点此登录或注册