我有一个窗体Form1,做主窗体
还有一个窗体form2,做为主窗体的参数窗体,对主窗体上的控件进行配制。
现在我要用form2去控制form1上的edit.text='A',
我觉得在form2中直接使用form1.edit.text='A',这种方式不太好,
请教这种窗体间的控制,怎么做才是最好的?
还有一个窗体form2,做为主窗体的参数窗体,对主窗体上的控件进行配制。
现在我要用form2去控制form1上的edit.text='A',
我觉得在form2中直接使用form1.edit.text='A',这种方式不太好,
请教这种窗体间的控制,怎么做才是最好的?
====================================================
是指书写形式不太好吗?可以在form1或者form2中设置一个有意义的属性,然后对属性进行操作。
您所说的全局变量是在哪里声明呢?楼主的var Form1、Form2,又是在哪里声明的呢?简约、朴素不见得就不好。过份追求理论意义上的缜密,只会使事情变得繁琐。个人之见,说错勿怪。
然后让fom2.edit:=form1.edit,这种不晓得是不是一种好的方法,
各位,你们在处理这种窗体间的参数传递是怎么处理的呢,如果不能使用ini等配置文件的情况下,
大家一起讨论一下!
然后让fom2.edit:=form1.edit,这种不晓得是不是一种好的方法,
各位,你们在处理这种窗体间的参数传递是怎么处理的呢,如果不能使用ini等配置文件的情况下,
大家一起讨论一下!
一个窗体引用另一个窗体在实际应用中很多,但一定要尽量避免两个窗体之间的互相引用。
我们有时间是在公共单元文件中声明一个全局变量,如Tstringlist等可以传递多个值。
请问,单元的
interface区
声明了一个
var
Form1: TForm1;这是不是全局变量?1、你在公共单元中声明一个全局变量是不是画蛇添足呢?2、难道你的公共单元不需要用uses引用到想用它的单元中去?
还有一个窗体form2,做为主窗体的参数窗体,对主窗体上的控件进行配制。 如果Form2是ShowModal的窗体,那么我会这么干
Form2加一个public的方法叫Show**(如ShowConfig)
返回值为Integer(其实就是ModalResult)
带一个或多个var的参数(参数太多封装为记录体)
因为是ShowModal的窗体,所以Form2的任务是返回这个var的记录体,并告诉Form1,用户点的是确定还是取消(判断返回值)
只管自己要做的事,并不应该干涉别人(Form1拿这个记录体要干嘛,Form2管不着)如果Form2是Show的窗体,那我会这么干
Form2加一个public的方法叫Show**(如ShowConfig)
返回值不重要了,参数为能够初始化Form2所需要的信息
Form2增加一个或多个事件(如SelectChanged、TextChanged等)
Form2改变了什么,就调用相应的事件
Form1想要那哪个就增加相应的事件处理就行了
同样,Form2只管自己要做的事,Form1需要事件通知它就订阅,Form2同样管不着
假如我要在Form2中实时控制form1的某个控件的属性,
好像按你的方法,不太好办哦?
--------------------------------------
公用单元的变量不只是给某个FORM用的,应用程序内所有的FORM都可以用到,
每FORM只记住这个是公用单元,但要是引FORM内值的话,一个窗体还好,若有多个窗体去引用这个FORM值,太多的话思路就不够清晰。
至少我不喜欢直接去form1.edit.text='A'这样做,呵呵
同问。
那请问您是怎么做的呢?能否写一个例子展示一下您如何在公共单元声明,又如何使用?
希望不会很繁琐。PS:Form1.Edit.Text := 'A'; ---- 这样做 有什么不可避免的风险呢?
很多情况下不需要这样取值,如果它只是个配置信息,我全完可以从配置文件中得到不是更好。
或者在SHOWMODAL后去全局量中得到相应个值。
我不想抬杠,只是想表明一点,窗体间相互独立些不是更加合理吗。
消息,需要接收消息一方建立一个消息循环。这样做可以,但要看是否需要这样做。如果根本不需要,那就自寻烦恼了。
二、如果不用Form1.Edit.Text := 'assss'这样直接赋值,可以在TForm1里增加一个方法,用方法赋值。这样比较符合类封装原则。但是,从单元引用的角度说,这样做与Form1.Edit.Text := 'assss'基本无异。
这样做的演示如下:
unit Unit1;interfacetype
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure SetEdit1Text(NewText: string);
end;var
Form1: TForm1;implementationuses Unit2;////在这里引用,没有循环引用的问题。{$R *.dfm}procedure TForm1.SetEdit1Text(NewText: string);
begin
Edit1.Text := NewText;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Show;
end;end.
////===================
unit Unit2;interface
//...
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;var
Form2: TForm2;implementationuses Unit1;////在这里引用,没有循环引用的问题。{$R *.dfm}procedure TForm2.Button1Click(Sender: TObject);
begin
Form1.SetEdit1Text('abcdefg');///还是要Form1......这样做
end;end.三、关于在公共单元声明一个全局变量,会更好、更安全、更简洁,----我实在不知如何做但并不是不推荐使用公共单元。还是那句话:要分场合。把一切都放入公共单元,我认为并不可行。
说的没错。这个思路在编程过程中是很重要的。我也是这样做的----比如一些普通的全局变量、初始化设置信息、字符串资源等。
但任何措施都不是万能的,我们总是要做一些取舍,如果为了将来可能或不可能的修改而提前付出巨大的劳动量,就不值得了。----这还是我说的“繁琐”的利弊之处。
对于Form1.Edit.Text := 'assss'来说,不同的实现方式,无论信息经何处周转,又从何处来,但它总归是要去向Form1的吧!也就是说,代码中总归要出现一个Form1----能理解我要表达的意思吗?千万别误会。我也没有抬杠的意思。讨论问题嘛。如有不礼貌的地方,请您谅解。
是的,窗体间尽量独立。但只要它们之间要交换信息,就没有也不可能有绝对的独立。
我可以这样理解吗?
呵呵,多谢lihuasoft兄的赐教。
unit FormMain;type
TFormMain...
Edit1
Edit2
Edit3
...
public
procedure ReadSetupInfo;
end;procedure TFormMain.ReadSetupInfo;
begin
//从INI文件,或全局的设置信息表中读出设置信息并更新FormMain
Edit1.text := ...;
Edit2.text := ...;
Edit3.text := ...;
....
end;
end.
unit FormSetup;type
TFormSetup...
Button
...
procedure Button1Click...
end;procedure TFormMain.Button1Click...
begin
//把更新后的设置信息写入INI文件或全局设置信息表
FormMain.ReadSetupInfo;///根据设置信息重置FormMain
{注意,这里还是要用“FormMain.”,也就是说,这个窗体单元还是要引用unit FormMain
这就是我一直“纠缠不清”的问题所在}
end;end.
unit FormMain;type
TFormMain...
Edit1
Edit2
Edit3
...
public
procedure ReadSetupInfo;
end;procedure TFormMain.ReadSetupInfo;
begin
//从INI文件,或全局的设置信息表中读出设置信息并更新FormMain
Edit1.text := ...;
Edit2.text := ...;
Edit3.text := ...;
....
end;
end.
unit FormSetup;type
TFormSetup...
Button
...
procedure Button1Click...
end;procedure TFormMain.Button1Click...
begin
//把更新后的设置信息写入INI文件或全局设置信息表
FormMain.ReadSetupInfo;///根据设置信息重置FormMain
{注意,这里还是要用“FormMain.”,也就是说,这个窗体单元还是要引用unit FormMain
这就是我一直“纠缠不清”的问题所在}
end;end.
奇怪,刚才连发了两遍不见显示。再发一遍:我猜测,前面“双方”讨论的方向可能发生了偏离。如果楼上几位要表达的意思是这样,我完全赞同,并且也推荐楼主这样写:
unit FormMain;type
TFormMain...
Edit1
Edit2
Edit3
...
public
procedure ReadSetupInfo;
end;procedure TFormMain.ReadSetupInfo;
begin
//从INI文件,或全局的设置信息表中读出设置信息并更新FormMain
Edit1.text := ...;
Edit2.text := ...;
Edit3.text := ...;
....
end;
end.
unit FormSetup;type
TFormSetup...
Button
...
procedure Button1Click...
end;procedure TFormMain.Button1Click...
begin
//把更新后的设置信息写入INI文件或全局设置信息表
FormMain.ReadSetupInfo;///根据设置信息重置FormMain
{注意,这里还是要用“FormMain.”,也就是说,这个窗体单元还是要引用unit FormMain
这就是我一直“纠缠不清”的问题所在}
end;end.
多看看控件源代码,停留在使用控件的层面上不是太好,如果能写控件的话,你就很会有感觉了把Form1看成你写的东西,Form2看成是人家的东西,你可能根本就不知道人家Form2中有哪些东西
但是你工作做得好的话就直接发布一个事件,分工明确对以后的维护有很大的帮助,灵活性更高,能够在一定层度上应付需求变更,通常写代码花的时间比找代码花的时间要少(敲代码也要找对地方敲嘛)。事件使用的例子Form1发布事件OnMyDataChanged
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
ComboBox1: TComboBox;
procedure ComboBox1CloseUp(Sender: TObject);
private
FOnMyDataChanged: TGetStrProc;
procedure SetOnMyDataChanged(const Value: TGetStrProc);
public
property OnMyDataChanged: TGetStrProc read FOnMyDataChanged write SetOnMyDataChanged;
end;var
Form1: TForm1;implementation{$R *.dfm}{ TForm1 }procedure TForm1.SetOnMyDataChanged(const Value: TGetStrProc);
begin
FOnMyDataChanged := Value;
end;procedure TForm1.ComboBox1CloseUp(Sender: TObject);
begin
if Assigned(FOnMyDataChanged) then
FOnMyDataChanged(ComboBox1.Text);
end;end.
Form2使用事件Form1.OnMyDataChanged
unit Unit2;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure Form1DataChanged(const S: string);
public
{ Public declarations }
end;var
Form2: TForm2;implementationuses Unit1;{$R *.dfm}procedure TForm2.Button1Click(Sender: TObject);
begin
Form1 := TForm1.Create(Application);
Form1.OnMyDataChanged := Form1DataChanged;
end;procedure TForm2.Form1DataChanged(const S: string);
begin
Text := S;
end;end.
再次回贴。
我“纠缠不清”的观点,在于有人说在Form2里用“Form1.XXX”这样不好,认为要在公共单元加一个全局变量去操作。
至于说用“方法”(而不是您说的“事件”),仍然会出现“Form1.XXX”这种形式。
并且,使用“方法”,前面我已经有代码了。下面是昨天下午回贴后没有显示的内容:
前面双方讨论的方向可能发生了偏离。如果楼上几位要表达的意思是这样,我完全赞同,并且也推荐楼主这样写:unit FormMain;type
TFormMain...
Edit1
Edit2
Edit3
...
public
procedure ReadSetupInfo;
end;procedure TFormMain.ReadSetupInfo;
begin
//从INI文件,或全局的设置信息表中读出设置信息并更新FormMain
Edit1.text := ...;
Edit2.text := ...;
Edit3.text := ...;
....
end;
end.
unit FormSetup;type
TFormSetup...
Button
...
procedure Button1Click...
end;procedure TFormMain.Button1Click...
begin
//把更新后的设置信息写入INI文件或全局设置信息表
FormMain.ReadSetupInfo;///根据设置信息重置FormMain
{注意,这里还是要用“FormMain.”,也就是说,这个窗体单元还是要引用unit FormMain
这就是我一直“纠缠不清”的问题所在}
end;end.
昨天经过实践,将form1的控件做参传到form2就可以达到form2中不引用form1
使用配置文件,并不会导致“Form2中不能实时控制Form1”本人退出本贴的讨论。(自己都看花眼了)^_^
实时控制,lake_cx说的事件传递很不错,学了一招。
或者用消息传递,把form1的窗体句柄传过去也可以达到目的。