0

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

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

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

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

ENP 表单有一个名为 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;

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

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

如果在类中发送,则 clearGrid 方法有效。有任何想法吗 ?。

4

2 回答 2

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;

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

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

我希望这有帮助。

于 2013-07-19T10:51:56.660 回答
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(让用户有机会返回TENP实例并再次单击opAgregar按钮以创建更多实例TAddEnp):

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

其次是TAddEnp依赖于ENP变量:

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

这确实会失败:

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

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

原因是ENP未赋值(默认为nil),所以在里面clearGridSelf也将是nil

您可以实施的解决方案

  1. TENP保留一个和TAddEnp周围的单个实例,ShowModal用于强制模态以防止用户多次单击相同的按钮。
  2. 保留您现有的行为,但将每个实例Show绑定到创建它的实例。TAddEnpTENP

对于第一个解决方案,您的代码将变为:

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;

这里添加依赖:

procedure TAddEnp.AgregarClick(Sender: TObject);
var
  ENP: TENP;
begin
//...
  ENP := Owner as TENP; // Owner will be of type TENP because of the Create(Self) in the ENP1Click method
  ENP.clearGrid();
  ENP.populateGrid();
end;
于 2013-07-19T08:43:29.550 回答