Delphi 从其他表单访问DBGrid1.Columns[1].Title.Caption

Delphi 从其他表单访问DBGrid1.Columns[1].Title.Caption,delphi,mdichild,dbgrid,mdiparent,tform,Delphi,Mdichild,Dbgrid,Mdiparent,Tform,我正在尝试从另一个表单访问dbgrid.field的标题 我在这里使用MDI,两个表单都是MDI子级 我试图从另一个窗体执行以下ShowMessage,但它导致访问冲突: ShowMessage(Form1.DBGrid1.Columns[1].Title.Caption); // 1st try ShowMessage(Unit1.Form1.DBGrid1.Columns[1].Title.Caption); // 2nd try 已在两个窗体之间使用集合 错误消息是 模块中地址0000

我正在尝试从另一个表单访问dbgrid.field的
标题

我在这里使用MDI,两个表单都是MDI子级

我试图从另一个窗体执行以下
ShowMessage
,但它导致访问冲突:

ShowMessage(Form1.DBGrid1.Columns[1].Title.Caption); // 1st try

ShowMessage(Unit1.Form1.DBGrid1.Columns[1].Title.Caption); // 2nd try
已在两个窗体之间使用集合

错误消息是

模块中地址000010363F9处的访问冲突。读取地址00000000 6F0

我错过了什么


更新:这是这个案例的精确复制(RME)

MDI父级

unit MainUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus;

type
  TParentForm = class(TForm)
    mmMenu: TMainMenu;
    miForm1: TMenuItem;
    miForm2: TMenuItem;
    procedure miForm1Click(Sender: TObject);
    procedure miForm2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ParentForm: TParentForm;

implementation

uses
  Form1Unit, Form2Unit;

{$R *.dfm}

procedure TParentForm.miForm1Click(Sender: TObject);
begin
  TChildForm1.Create(self).Show;
end;

procedure TParentForm.miForm2Click(Sender: TObject);
begin
  TChildForm2.Create(self).Show;
end;

end.
MDI子窗体1

unit Form1Unit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Datasnap.DBClient,
  Datasnap.Provider, MemDS, DBAccess, Uni, UniProvider, MySQLUniProvider,
  Vcl.Grids, Vcl.DBGrids;

type
  TChildForm1 = class(TForm)
    dbgrd1: TDBGrid;
    ucn1: TUniConnection;
    mup1: TMySQLUniProvider;
    uq1: TUniQuery;
    dsp1: TDataSetProvider;
    cds1: TClientDataSet;
    ds1: TDataSource;
    smlntfldcds1actor_id: TSmallintField;
    strngfldcds1first_name: TStringField;
    strngfldcds1last_name: TStringField;
    dtmfldcds1last_update: TDateTimeField;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ChildForm1: TChildForm1;

implementation

uses
  MainUnit, Form2Unit;

{$R *.dfm}

end.
MDI子窗体2

unit Form2Unit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

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

var
  ChildForm2: TChildForm2;

implementation

uses
  MainUnit, Form1Unit;

{$R *.dfm}

procedure TChildForm2.btn1Click(Sender: TObject);
begin
  ShowMessage(Form1Unit.ChildForm1.dbgrd1.Columns[2].Title.Caption);
end;

end.
错误消息

模块“Project7.exe”中地址0081B314处的访问冲突。读到 地址:000003D0


可能有一个对象没有分配,我怀疑它可能是
列[1]
(注意
集合是基于零的索引,因此第一列是
列[0]

试试这个:

if(not Assigned(Form1)) then 
  raise Exception.Create('Form1 not assigned');

if(not Assigned(Form1.DBGrid1)) then 
  raise Exception.Create('Form1.DBGrid1 not assigned');

if(Form1.DBGrid1.Columns.Count < 2) then 
  raise Exception.Create('Form1.DBGrid1 has not the Columns[1] item');
如果(未分配(表格1)),则
引发异常。创建('Form1 not assigned');
如果(未赋值(Form1.DBGrid1)),则
引发异常。创建('Form1.DBGrid1 not assigned');
如果(Form1.DBGrid1.Columns.Count<2),则
Create('Form1.DBGrid1没有列[1]项');

编写类似于
Form1Unit.ChildForm1.dbgrd1.Columns[2].Title.Caption)的代码是在制造等待发生的事故,
因为它假定要操作的ChildForm1实例是自动创建的
ChildForm1

使用自动创建的表单(除了主表单之外)通常被认为是不好的做法,因为它会导致类似这样的事故,所以最好摆脱使用表单的习惯

从另一个窗体(或数据模块)访问一个窗体(或数据模块)时,一种不太容易发生事故的技术是在“其他”窗体上编写代码,这种方式要求您指定要操作的对象实例。大概是这样的:

procedure TChildForm2.DoSomethingWithForm1(Form1Instance : TForm1);
begin
  ShowMessage(Form1Instance.dbgrd1.Columns[2].Title.Caption);
end;

procedure TChildForm2.btn1Click(Sender: TObject);
begin
  DoSomethingWithForm1(Form1Unit.ChildForm1);
end;
这样做的意义在于,它迫使你思考你选择的是哪一个Form1实例 意思是,因为当你有多个相同的实例时,得到正确的答案是非常重要的
表单(即使您没有,因为它可能会提示您是否已创建实例)。

实际上,列已经存在于引用它的表单中。我指的是本案中的具体专栏。我不确定你给的代码是否有效。我尝试使用ShowMessage以相同的形式访问它,但它确实是使用-ShowMessage(DBGrid1.Columns[1].Title.Caption)执行的;所以我认为
Form1
对象没有赋值,或者它不属于预期的类类型。试着检查一下我忘了提到我在这里使用MDI。顺便说一下,这两个窗体都是MDI子窗体。是否确实Form1指向窗体的实例?。你能告诉我们你在哪里创建表单的代码吗?请在遇到错误时,将错误消息复制到你的问题上(右键单击消息窗口,然后按Ctrl-C)。请不要在评论中详述你的问题。您的问题。请显示您正在使用的代码,并在上下文中显示它,就像ShowMessage(…)这样的单个语句-读者不必猜测。您必须指定
ChildForm1:=TChildForm1.Create(Self);ChildForm1.Show()。在你的代码中,
ChildForm1
是零。所以,Juke。如果你按照@Fabrizio的建议检查Form1(等)的分配,你就会得到答案!或者至少有一个明确的迹象表明什么可能是错的,我知道。我刚从这里学到的。我已经更改了一些与此相关的代码。非常感谢你。