从另一个表单访问StringGrid

时间:2013-07-14 18:42:26

标签: delphi insert access-violation stringgrid

编辑正文以获取更多详细信息。

我有一个名为ENP的表单,在EnpView单元中定义。 ENP表单是在主窗体(TPrincipal)中单击工具栏项的处理程序事件中创建和显示的。

procedure TPrincipal.ENP1Click(Sender: TObject);
begin
  TENP.Create(self).Show();
end;

Enp表单知道(在公开声明中)clearGrid()消息。

ENP Form有一个名为StringGrid的TStringGrid。还有一个名为“添加”的按钮。单击“添加”按钮时,将创建另一个表单并显示:AddEnp表单,在EnpViewAdd单元中定义。

procedure TENP.opAgregarClick(Sender: TObject);
begin
  TAddEnp.Create(self).Show();
end;

AddEnp表单,有任何TEdits。输入的值必须在EnpView.StringGrid中添加。

我试试这个:

implementation

uses
  EnpView, Main;
procedure TAddEnp.AgregarClick(Sender: TObject);
begin

  { Agrego el nodo xml }
  Globals.Xml.agregarMuestra(muestra.Text);
  Globals.Xml.insertEnp(muestra.Text,golpes.Text,metros.Text);

  { Send messages to EnpView Form }
  ENP.clearGrid();
  ENP.populateGrid();

end;

第1行中的ClearGrid消息失败,存在访问冲突:

procedure TENP.clearGrid();
begin
  Self.StringGrid.RowCount := 2;
  Self.StringGrid.Rows[1].Clear();
end;

如果在类中发送,则clearGrid方法有效。有什么想法?。

2 个答案:

答案 0 :(得分:1)

在TAddENP中创建一个名为ENPForm的属性,并在创建后立即分配ENP表单。声明如下:

TAddENP = class(TForm)
private
  FENPForm: TENP;

// all of your already existing declarations

public
  property ENPForm: TENP read FENPForm write FENPForm;
end;

现在您可以参考ENP表格,您可以随意使用它。

在创建TAddENP表单期间,请执行以下操作:

procedure TENP.opAgregarClick(Sender: TObject);
var
  addForm: TAddENP;
begin
  addForm := TAddEnp.Create(Self);
  addForm.EnpForm := Self;
  addForm.Show;
end;

现在您创建了第二个表单,并为第一个表单提供了安全引用。他们现在可以安全地互相交谈。

我建议你避免让一个表单操作其他组件,因为这会增加它们之间的依赖关系。相反,声明公共方法来做到这一点,因此表单将取决于它们的接口,而不是它们的实现。

我希望这会有所帮助。

答案 1 :(得分:0)

从您的问题(我添加code-style以使其更清晰):

  

我有一个名为ENP的表单,在EnpView单元中定义。 ENP表单,   从单击工具栏项的处理程序事件创建并显示   在主要表格(TPrincipal)。

procedure TPrincipal.ENP1Click(Sender: TObject);
begin
  TENP.Create(self).Show();
end;

这与您的ENP表单变量无关 您创建TENP表单类的实例并使用Show显示该实例,但未分配ENP变量。
您无法将实例分配给ENP变量,因为每次单击按钮都会创建一个新实例(因此您有多个TENP实例)。

然后,您创建了TAddEnp实例和(从未声明的ENP变量)的复杂依赖。
您可以通过创建TAddEnp实例来实现此目的(为什么TAddEnp在此而不是TAddENP?)使用Show显示它(让用户有机会返回{ {1}}实例,然后再次点击TENP按钮创建更多opAgregar的实例:

TAddEnp

然后让procedure TENP.opAgregarClick(Sender: TObject); begin TAddEnp.Create(self).Show(); end; 依赖于TAddEnp变量:

ENP

这确实会失败:

  

第1行中的ClearGrid消息失败,存在访问冲突:

procedure TAddEnp.AgregarClick(Sender: TObject);
begin
//...
  ENP.clearGrid();
  ENP.populateGrid();
end;

原因是procedure TENP.clearGrid(); begin Self.StringGrid.RowCount := 2; Self.StringGrid.Rows[1].Clear(); end; 未分配(默认情况下为ENP),因此在nil内,clearGrid也将Self

您可以实施的解决方案

  1. 保留nilTENP的单个实例,使用TAddEnp强制模式以防止用户多次点击相同的按钮。
  2. 保留现有的ShowModal行为,但将每个Show实例绑定到从中创建的TAddEnp实例。
  3. 对于第一个解决方案,您的代码将变为:

    TENP

    procedure TPrincipal.ENP1Click(Sender: TObject);
    begin
      ENP := TENP.Create(Application);
      ENP.ShowModal();
      ENP.Release();
      ENP := nil;
    end;
    

    第二个将需要更多努力,因为您需要阻止使用现有变量。

    • 删除procedure TENP.opAgregarClick(Sender: TObject); begin AddEnp := TAddEnp.Create(Application); AddEnp.ShowModal(); AddEnp.Release(); AddEnp := nil; end; 变量。
    • 删除ENP变量。

    修复AddENP - >方法中的self

    Self

    procedure TPrincipal.ENP1Click(Sender: TObject);
    begin
      TENP.Create(Self).Show();
    end;
    

    这里添加依赖项:

    procedure TENP.opAgregarClick(Sender: TObject);
    begin
      TAddEnp.Create(Self).Show();
    end;