zzzzzzz7 发表于 2025-12-6 21:11:29

请教 我unit1的edit.text可以传给另一个窗口unot2 为什么2不能反传1窗口?

unit Unit2;

{$mode ObjFPC}{$H+}

interface

uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs,StdCtrls,Unit1       ;////<----------这里unit1报错 unit2.pas(8,71) Error: Circular unit reference between Unit2 and Unit1

type

{ TForm2 }

TForm2 = class(TForm)
    Button1: TButton;
    F2Edit1: TEdit;
    f2Edit2: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
private

public

end;

var
Form2: TForm2;

implementation

{$R *.lfm}

{ TForm2 }

procedure TForm2.FormCreate(Sender: TObject);
begin

end;

procedure TForm2.Button1Click(Sender: TObject);
begin
//F2Edit1.Text:=form1.Edit4.Text;
//F2Edit2.Text:=form1.edit5.Text;
end;

end.



//idelazarus但是我窗口1的text是可以传给窗口2edit.text 窗口二就不能写传窗口1了- -!大哥些 求解
                                                   

zzzzzzz7 发表于 2025-12-6 21:12:39

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtDlgs,
ExtCtrls, Grids, ComCtrls,Unit2, Menus;//《-------------------窗口1的这里就不会报错

type

{ TForm1 }

TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Image1: TImage;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    ListView1: TListView;
    MenuItem1: TMenuItem;
    PopupMenu1: TPopupMenu;
    SaveDialog1: TSaveDialog;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure DrawGrid1Click(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
    procedure Edit3Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Image1Click(Sender: TObject);
    procedure Label3Click(Sender: TObject);
    procedure MenuItem1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
private

public


end;

var
Form1: TForm1;

st:string;
      f1_edit:string;
f2_edit:string;
a:boolean=true ;
b:integer=0;

implementation

type
rec =record
name:string;
sex:string;
age:integer;
end;

{$R *.lfm}

{ TForm1 }
procedure f( str1:string ; str2:string);
begin
    // TForm1.edit3.Text:=inttostr( strtoint(str1)+strtoint(str2)) ;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
t1:string;
t2:string;
a:real;
b:real ;
c:real ;
begin
   t1:=edit1.Text;
   t2:=edit2.Text;
   a:=strtofloat(t1);
   b:=strtofloat(t2);
   c:=a+b;
   edit3.Text:=floattostr(c);

end;

procedure TForm1.Button2Click(Sender: TObject);
var
    tf:textfile;
a:integer=911;
begin
   if savedialog1.Execute then
   begin
       assignfile(tf,savedialog1.FileName);
       rewrite(tf);
       write(tf,a);
       closefile(tf);
   end;

end;

procedure TForm1.Button3Click(Sender: TObject);
var
str1:string='tttttt';
begin
   timer1.Interval:=5000;
    showmessage(str1);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
f1_edit:=edit4.Text;
f2_edit:=edit5.Text;
//form1.Hide;
form2.f2Edit1.Text:=f1_edit;
form2.f2Edit2.Text:=f2_edit;
end;



procedure TForm1.DrawGrid1Click(Sender: TObject);
begin

end;

procedure TForm1.Edit1Change(Sender: TObject);
begin

end;

procedure TForm1.Edit3Change(Sender: TObject);
begin

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
      close;

end;

procedure TForm1.Image1Click(Sender: TObject);
begin

end;

procedure TForm1.Label3Click(Sender: TObject);
begin

end;

procedure TForm1.MenuItem1Click(Sender: TObject);
begin

end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
b:integer=254 ;
begin
// if a=true then
// image1.Top:=image1.Top+30
// else
// image1.Top:=image1.Top-30;
   while b>0 do
   begin
       image1.Top:=image1.Top-1;
       b:=b-1;
   end;
   //a:=not a;
end;

end.
//这是窗口1代码

FishC 发表于 2025-12-6 21:12:42

鱼油你好!

你的问题是关于两个窗口之间数据双向传递的。从代码看,Unit2 已经 uses 了 Unit1,所以从 Unit1 传数据到 Unit2 是可行的。但反过来不行,主要是因为 Unit2 没有获得 Unit1 窗口实例的引用。

简单来说:你知道 Unit1 长什么样(因为有 uses),但不知道具体要操作哪一个 Unit1。

以下是解决方案:

核心思路:
在 Unit1 中创建/显示 Unit2 时,将 Unit1 自己的引用(例如 Self)传递给 Unit2。

操作步骤:

1.在 Unit2 中,定义一个变量来保存对 Unit1 实例的引用。
2.在 Unit1 中,创建 Unit2 时,将自己的引用赋给 Unit2 的这个变量。
3.在 Unit2 中,就可以通过这个变量来修改 Unit1 的控件了。

示例代码:

在 Unit2 中:

unit Unit2;

interface

uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit1;

type
TForm2 = class(TForm)
    Edit2: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
private
    // 定义一个变量,用于保存 Unit1 的窗口实例
    FMyForm1: TForm1;
public
    // 一个公共属性或方法,用于接收来自 Unit1 的引用
    property MyForm1: TForm1 write FMyForm1;
end;

implementation

procedure TForm2.Button1Click(Sender: TObject);
begin
// 当点击 Unit2 的按钮时,将 Edit2 的文本传回给 Unit1 的 Edit1
if Assigned(FMyForm1) then // 先检查引用是否存在,避免出错
    FMyForm1.Edit1.Text := Edit2.Text;
end;

end.


在 Unit1 中:

unit Unit1;

interface

uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2; // 也需要 uses Unit2

type
TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
private
    Form2: TForm2; // 声明 Unit2 的窗体变量
public
    { public declarations }
end;

implementation

procedure TForm1.Button1Click(Sender: TObject);
begin
// 创建并显示 Unit2 的窗口
Form2 := TForm2.Create(nil);
try
    // 关键一步:将当前 Unit1 的实例(Self)传给 Unit2
    Form2.MyForm1 := Self;
    Form2.ShowModal; // 或使用 Show 方法,取决于你的需求
finally
    Form2.Free; // 如果是 ShowModal,通常这样释放
end;
end;

end.


注意事项:
*   确保 Unit1 和 Unit2 的窗体类名正确(示例中为 TForm1 和 TForm2)。
*   ShowModal 会阻塞直到窗口关闭,适合需要等待用户操作的场景;Show 则非阻塞。根据你的需求选择。
*   示例中使用了属性 (property) 来传递引用,你也可以在 Unit2 中定义一个公共方法(如 SetForm1)来完成同样的工作。
*   这种方式直接操作了另一个窗体的控件,在简单程序中可以。对于更复杂的项目,建议在 Unit1 中提供公共方法(如 SetEditText)来设置文本,这样封装性更好。

这样修改后,Unit2 就能将数据传回给 Unit1 了。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

zzzzzzz7 发表于 2025-12-6 22:19:17

本帖最后由 zzzzzzz7 于 2025-12-6 22:20 编辑

FishC 发表于 2025-12-6 21:12
鱼油你好!

你的问题是关于两个窗口之间数据双向传递的。从代码看,Unit2 已经 uses 了 Unit1,所以从 U ...

unit Unit2;

{$mode ObjFPC}{$H+}

interface
//uses Unit1;
//uses Unit1   ;//如果我把 unit1写出来就会报错
uses
Classes,SysUtils, Forms, Controls, Graphics, Dialogs,StdCtrls; //<--

type

{ TForm2 }

TForm2 = class(TForm)
    Button1: TButton;
    F2Edit1: TEdit;
    f2Edit2: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
private
   // 定义一个变量,用于保存 Unit1 的窗口实例
    FMyForm1: TForm1;         //错误出现
public
    // 一个公共属性或方法,用于接收来自 Unit1 的引用
    property MyForm1: TForm1 write;          //错误出现

end;
                                                      

//编译项目,目标:G:\AAApascaltext\project1.exe: 退出代码1,错误: 4
unit2.pas(25,15) Error: Identifier not found "TForm1"
unit2.pas(25,21) Error: Error in type definition
unit2.pas(28,23) Error: Identifier not found "TForm1"
unit2.pas(28,35) Error: Illegal symbol for property access

FishC 发表于 2025-12-6 22:20:16

zzzzzzz7 发表于 2025-12-06 22:19
FishC 发表于 2025-12-6 21:12
鱼油你好!

你的问 ...

你的代码显示 Unit2 没有在 interface 部分使用 Unit1,这是正确的做法。要解决双向传递问题,你可以按照下面的方法修改:

首先在 Unit2 中:
1. 定义一个变量来存储 Unit1 的引用
2. 创建一个属性或方法来接收这个引用

修改后的 Unit2 代码:

unit Unit2;

{$mode ObjFPC}{$H+}

interface

uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
TForm2 = class(TForm)
    f2Edit1: TEdit;
    f2Edit2: TEdit;
    Button1: TButton;// 添加一个按钮来测试传回数据
    procedure Button1Click(Sender: TObject);
private
    // 添加一个私有变量来存储 Unit1 的引用
    FMyForm1: TObject; // 或者更具体的类型
public
    // 公共属性,用于设置 Form1 的引用
    property MyForm1: TObject write FMyForm1;
end;

var
Form2: TForm2;

implementation

{$R *.lfm}

procedure TForm2.Button1Click(Sender: TObject);
var
Form1Ref: TForm; // 根据实际情况调整类型
begin
// 将数据传回 Unit1
if Assigned(FMyForm1) then
begin
    // 需要将 FMyForm1 转换为正确的类型
    // 这里假设 FMyForm1 是 TForm1 类型
    Form1Ref := TForm(FMyForm1);
   
    // 如果知道具体的控件名,可以这样设置
    // 注意:这里需要访问 Unit1 中的控件
    // 你可以使用 with 语句,或者更好的方式是:
    // 在 Unit1 中创建一个公共方法来接收数据
   
    // 示例:将数据传回 Unit1 的某个 Edit
    // (Form1Ref as TForm1).Edit1.Text := f2Edit1.Text;
   
    // 为了安全起见,我们可以使用 RTTI 或者更好的设计模式
end;
end;

end.

更安全的方式是在 Unit1 中创建一个公共方法:

首先,修改 Unit1:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2;

type
TForm1 = class(TForm)
    // ... 你的控件声明
    Edit1: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Button4: TButton;
    procedure Button4Click(Sender: TObject);
private
    { private declarations }
public
    // 添加一个公共方法来接收 Unit2 传来的数据
    procedure ReceiveDataFromUnit2(const AData: string);
end;

var
Form1: TForm1;

implementation

{$R *.lfm}

procedure TForm1.Button4Click(Sender: TObject);
begin
// 将数据传给 Unit2 并显示 Unit2
if not Assigned(Form2) then
    Form2 := TForm2.Create(nil);

// 将当前 Form1 的引用传给 Form2
Form2.MyForm1 := Self;

// 传递数据
Form2.f2Edit1.Text := Edit4.Text;
Form2.f2Edit2.Text := Edit5.Text;

Form2.Show;
end;

procedure TForm1.ReceiveDataFromUnit2(const AData: string);
begin
// 接收来自 Unit2 的数据
Edit1.Text := AData; // 或者任何你想设置的控件
end;

end.

然后,修改 Unit2 的 Button1Click 方法:

procedure TForm2.Button1Click(Sender: TObject);
begin
// 调用 Unit1 的公共方法来传递数据
if Assigned(FMyForm1) then
begin
    // 安全地调用公共方法
    // 这里假设 FMyForm1 是 TForm1 类型
    (FMyForm1 as TForm1).ReceiveDataFromUnit2(f2Edit1.Text);
end;
end;

关键点总结:
1. 在 Unit1 中创建 Unit2 时,将 Self(当前 Unit1 实例)传递给 Unit2
2. 在 Unit2 中存储这个引用
3. 通过这个引用调用 Unit1 的公共方法来传递数据
4. 这样可以避免循环引用问题,同时实现双向数据传递

这样修改后,Unit2 就能将数据传回 Unit1 了。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 请教 我unit1的edit.text可以传给另一个窗口unot2 为什么2不能反传1窗口?