0

我有一个自定义组件类,用作将评论和用户详细信息等加载到表单的框架。Class 是面板的子类,包含 3 个标签和一个备忘录。

在关闭我的表单或尝试释放对象时,我收到“无效指针操作”错误。我知道这是因为尝试两次释放对象,或者访问不可用的 RAM。但是,我不知道如何解决它。这让我有点退缩,因为我必须加载关于不同主题的不同评论,而且在我清除当前评论的形式之前我不能。

这是与类相关的代码:

    type
      TSkeleton = class(TPanel)
        private
        fName : TLabel;
        fStudNo : TLabel;
        fTimeAndDate : TLabel;
        fComment : TMemo;
     public
       Constructor Create (AOwner: TComponent); overload; override;
       constructor Create(AOwner:TForm; sName, sStudNo, sTime, sDate, sComment: string; ComCount: integer); overload;
 end;
{ TSkeleton }

constructor TSkeleton.Create(AOwner: TComponent);
begin
//
end;

constructor TSkeleton.Create(AOwner: TForm; sName, sStudNo, sTime, sDate,
  sComment: string; ComCount: integer);
begin
  inherited Create(AOwner);
  Parent := AOwner;
  Width := 800;
  Height := 250;
  Top := 448+((ComCount-1)*250);
  Left := 16;
  BevelInner := bvSpace;
  BevelOuter := bvLowered;

  fName := TLabel.Create(fName);
  self.InsertControl(fName);
  with fName do
  begin
   Caption := sName;
   Font.Name := 'Garamond';
   Font.Size  := 30;
   Left := 7;
   Top := 4;
  end;

  fStudNo := TLabel.Create(fStudNo);
  self.InsertControl(fStudNo);
    with fStudNo do
      begin
       Caption := sStudNo;
       Font.Name := 'Garamond';
       Font.Size  := 15;
       Left := 15;
       Top := 52;
      end;

  fTimeAndDate := TLabel.Create(fTimeAndDate);
  self.InsertControl(fTimeAndDate);
    with fTimeAndDate do
      begin
       Caption := sTime + ' ' + sDate;
       Font.Name := 'Garamond';
       Font.Size  := 20;
       Left := 583;
       Top := 4;
      end;

  fComment := TMemo.Create(fComment);
  self.InsertControl(fComment);
    with fComment do
      begin
       Lines.Add(sComment);
       Font.Name := 'Garamond';
       Font.Size  := 12;
       Left := 152;
       Top := 56;
       Height := 161;
       Width := 633;
       ReadOnly := True;
       ScrollBars := ssVertical;
      end;

end;

如果您想查看使用的其他代码(读取文本文件、创建对象数组等),请说出来。它与课程没有直接关系,所以我认为没有必要。

先感谢您。

编辑:基于@Remy Lebeau 的代码和@NGLN 的评论,我决定发布所有必要的内容。

根据@Remy 的代码修复课程后,我仍然收到错误消息。这让我相信错误出在我使用类的地方,尤其是在我创建的对象数组中。

以前,我的代码是

  for i := 0 to ComCount-1 do
  begin
    fArrObjects[i+1] :=  TSkeleton.Create(TargetForm);
    with fArrObjects[i+1] do
    begin
      Parent := TargetForm;
      TheName := fArrComments[i][0];
      StudNo := fArrComments[i][1];
      Time := fArrComments[i][2];
      Date := fArrComments[i][3];
      Comment := fArrComments[i][4];
      ComCount := i+1;
    end;

改变

fArrObjects[i+1]

 fArrObjects[i]

解决了这个问题。

感谢@Remy 纠正课堂上的错误。

4

1 回答 1

4

您的代码存在一些问题。

Parent := AOwner;

不要Parent在构造函数内部设置 from 。调用者有责任Parent在对象完全构造后设置。

您没有定义析构函数,并且您正在使用nilOwners 创建您的子对象。TSkeleton应该是所有者,例如:

//fName := TLabel.Create(fName);
fName := TLabel.Create(Self);
...

你不应该InsertControl()直接打电话。请改用该Parent属性,例如:

//self.InsertControl(fName);
fName.Parent := Self;
...

为什么你有两个构造函数?您重写的构造函数不做任何事情,甚至不调用基本构造函数,并且在设计时不调用您的自定义构造函数(除非您有其他代码正在以TSkeleton可编程方式创建实例)。我建议您摆脱自定义构造函数并公开发布的属性以根据需要操作子控件。

最后,由于您正在创建子组件,因此您应该通过TComponent.SetSubComponen().

话虽如此,尝试更像这样的东西:

type
  TSkeleton = class(TPanel)
  private
    fName : TLabel;
    fStudNo : TLabel;
    fTimeAndDate : TLabel;
    fComment : TMemo;

    fTime: string;
    fDate: string;
    fComCount: Integer;

    function GetTheName: string;
    procedure SetTheName(const AValue: string);
    function GetStudNo: string;
    procedure SetStudNo(const AValue: string);
    procedure SetTime(const AValue: string);
    procedure SetDate(const AValue: string);
    function GetComment: string;
    procedure SetComment(const AValue: string);
    procedure SetComCount(AValue: integer);

  public
    constructor Create (AOwner: TComponent); override;

  published
    property TheName: string read GetTheName write SetTheName;
    property StudNo: string read GetStudNo write SetStudNo;
    property Time: string read fTime write SetTime;
    property Date: string read fDate write SetDate;
    property Comment: string read GetComment write SetComment;
    property ComCount: integer read fComCount write SetComCount;
  end;

constructor TSkeleton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  Width := 800;
  Height := 250;
  Left := 16;
  BevelInner := bvSpace;
  BevelOuter := bvLowered;

  fName := TLabel.Create(Self);
  fName.SetSubComponent(True);
  fName.Parent := Self;
  fName.Font.Name := 'Garamond';
  fName.Font.Size  := 30;
  fName.Left := 7;
  fName.Top := 4;

  fStudNo := TLabel.Create(Self);
  fStudNo.SetSubComponent(True);
  fStudNo.Parent := Self;
  fStudNo.Font.Name := 'Garamond';
  fStudNo.Font.Size  := 15;
  fStudNo.Left := 15;
  fStudNo.Top := 52;

  fTimeAndDate := TLabel.Create(Self);
  fTimeAndDate.SetSubComponent(True);
  fTimeAndDate.Parent := Self;
  fTimeAndDate.Font.Name := 'Garamond';
  fTimeAndDate.Font.Size  := 20;
  fTimeAndDate.Left := 583;
  fTimeAndDate.Top := 4;

  fComment := TMemo.Create(Self);
  fComment.SetSubComponent(True);
  fComment.Parent := Self;
  fComment.Font.Name := 'Garamond';
  fComment.Font.Size  := 12;
  fComment.Left := 152;
  fComment.Top := 56;
  fComment.Height := 161;
  fComment.Width := 633;
  fComment.ReadOnly := True;
  fComment.ScrollBars := ssVertical;
end;

function TSkeleton.GetTheName: string;
begin
  Result := fName.Caption;
end;

procedure TSkeleton.SetTheName(const AValue: string);
begin
  fName.Caption := AValue;
end;

function TSkeleton.GetStudNo: string;
begin
  Result := fStudNo.Caption;
end;

procedure TSkeleton.SetStudNo(const AValue: string);
begin
  fStudNo.Caption := AValue;
end;

procedure TSkeleton.SetTime(const AValue: string);
begin
  if fTime <> AValue then
  begin
    fTime := AValue;
    fTimeAndDate.Caption := fTime + ' ' + fDate;
  end;
end;

procedure TSkeleton.SetDate(const AValue: string);
begin
  if fDate <> AValue then
  begin
    fDate := AValue;
    fTimeAndDate.Caption := fTime + ' ' + fDate;
  end;
end;

function TSkeleton.GetComment: string;
begin
  Result := fComment.Text;
end;

procedure TSkeleton.SetComment(const AValue: string);
begin
  fComment.Text := AValue;
end;

procedure TSkeleton.SetComCount(AValue: integer);
begin
  if fComCount <> AValue then
  begin
    fComCount := AValue;
    Top := 448+((FComCount-1)*250);
  end;
end;
于 2013-09-27T00:19:55.667 回答