关于窗体重用。不知道这是不是继承(200分)

L

lcl_003

Unregistered / Unconfirmed
GUEST, unregistred user!
关于窗体重用。不知道这是不是继承

我现在了解了重用和继承的作用了,也了解了frame。但是还不是很透彻。
对于我的情况我不知道到底属于什么情况,哪位高手给说说
比如我在按钮的click里动态创建窗体,并不判断这个窗体是否存在,因为
可以允许打开多个这样的窗体。
form1:=Tform1.create(application);
form1.show;
那问题就出现了,我点几次按钮就创建几个同样的窗体,这些窗体之间有
什么关系?我在这些窗体里定义的变量有什么关系?
我做了个测试,我在主窗体里有个按钮,按钮的click里动态创建form2,
form2里有个chart,一个timer,我让form2一创建timer就每隔100豪秒往chart
上画线(数值加1)。运行后我先创建一个form2,当线(series1)的数值
到达100之后再创建一个form2,我发现我第二次创建的form2里的series1也在
画线,只是数值马上会和我第一次创建的form2里的数值相等,这是为什么?
怎么样才能解决?就是说我创建的窗体是完全一样的,代码和功能是完全相同的
但是如何让他们互相不干扰?是继承吗?
 
在窗体里用到窗体名的话就用Self.xxxx

这样就不会干扰了
 
有意思的问题
 
Delphi每个Form其实是一个类(TForm1)

delphi程序自动给你加上了Application.createform

给你创建了这个类的一个对象(Form1)

所以你可以用Form1.xxxx

要OOP,就要使用类似于Self.xxxx

建议看看有关OOP的内容,类、对象、继承。。。等基础概念先了解
 
有继承和复制
你说的那种是复制
 
是一个类的多个实例吧,关于面向对象和继承的概念建议看一下C++,因为似乎没有专门讲
Object Pascal的。
 
rustle,我的代码很简单,在那里用Self.xxxx?

unit1

procedure TForm1.Button1Click(Sender: TObject);
begin
form2:=Tform2.Create(application);
form2.Show;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
i:=0;
end;


unit2

procedure TForm2.Timer1Timer(Sender: TObject);
begin
i:=i+1;
self.series1.Add(i);
end;


antic_ant, 哪本书有讲复制?

zw84611, 给说说多个实例?

 
你这里的一句,
form1:=Tform1.create(application);
form1.show;
本身就是在多次运行时,就没有多大意义,因为你的目的是创建N个可以控制的
TForm1 窗体,但是你这样子,创建的所有 TForm1 都跟 form1 这个实例关联上,
到最终,你能够方便控制的只剩下最后一次创建的 TForm1了,
所以如果你打算能够很好地控制这些窗体,你可以用一个动态数组来保存

var
afrmMy: array of TForm1
//这个应该是在你想要的变量有效范围内申明
............
begin
count := high(afrmMy)-low(afrmMy)+1;
SetLength(afrmMy,count+1);
afrmMy[high(afrmMy)] := TForm1.Create(Application);
afrmMy[high(afrmMy)].show;
end;

这样子的话,还会不会产生干扰呢?你试试。
 
darnis,
>>你能够方便控制的只剩下最后一次创建的 TForm1了
的确是这样。

但是我如你所说我在创建form2是这样写
procedure TForm1.Button1Click(Sender: TObject);
var
afrmMy: array of TForm2;
count:integer;
begin
count := high(afrmMy)-low(afrmMy)+1;
SetLength(afrmMy,count+1);
afrmMy[high(afrmMy)] := TForm2.Create(Application);
afrmMy[high(afrmMy)].show;
end;

但还是会产生干扰:(
 
我觉得是i的域的问题,这段程序中没写清楚,但看样子其作用域是在form1中,
每个form2都用了同一个i,当然值是一样的。
form2是一个类的多个实例,和form1没有继承和复制的关系。
 
老兄,你把 afrmMy 声明成全局试试呢?
 
呵呵,form2是定义在unit2里面的全局变量,你每次都create的实际上都是同一个它,
当然会有影响
procedure TForm1.Button1Click(Sender: TObject);
begin
form2:=Tform2.Create(application);
form2.Show;
end;

 
xtall, 我也感觉是i有问题,我把i定义为全局变量了。但是谁能清楚的说说这是怎么回事?
darnis, 把afrmMy 定义全局变量也还是不行;(
 
我给你一个建议:如果要通过一个窗体创建另一个窗体,最佳解决方案应该是采用MDI,创建窗体设为
主窗体,被创建窗体为子窗体,这样你就可以很好地控制了。
如果你不限制子窗体的创建数的话,只要:
subForm:=TsubForm.create(self);
subform.show;
如果你要限制子窗体的创建数的话,可以利用self.MDIChildCount和self.MDIChildRen这两个属性很
容易地任意你控制了,比如说:
for i:=0 to MDIChildCount-1 do
begin
if MIDChildRen is TSubForm then
begin
MDIChildRen.show;
exit;
end;
end;
subform:=Tsubform.create(self);
subform.show;
 
先前没有注意你的源码。

如果你的 i 是在 TForm2 里的一个变量,比如说 private 部分声明的,
那应该不会产生干扰的。
那你的 i 是全局的,i 是只在Form1 创建时初始化为0,也就只有你第一次创建的 form2
用到的 i 的初始值才是0,其它的 form2 在创建时, i 可能就已经不是0值了。
所以你的初始化就有问题。

另外如果你的 form2 本身比较复杂的话,可能有一定的差异,第一次创建时,可能要耗
比较长的时间,但接着再创建的窗体可能很快就好了(只是创建过程),也是可以理解的。
 
既然是全局变量,第一个form2用的是这个i,第二个form2用的还是这个i,当然是同一个值
 
多谢darnis, delphilai,我找darnis说的在form2的private生明i就没有问题了。但是我
的实际问题要复杂,能不能具体的说说我上面说的情况到底是继承、多实例、重用?

我的实际情况是在一个线程里定时从另外机器读数据,一个窗体(form2,就是要创建多个的窗体)
是mdi的子窗体,用来读线程的数据来画线。这个窗体里有一个chart,一个combobox,一个timer
combobox是用来选择画那些数据。

当线程接受到数据判断有效就启动form2里的timer来画线,画完timer就停止。combobox是用来
选择画线程接受来的数据的哪部分。

这种情况和上面的一样吗,有什么好的建议?
 
unit1

procedure TForm1.Button1Click(Sender: TObject);
begin
form2:=Tform2.Create(application);
form2.Show;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
i:=0;
end;


unit2

procedure TForm2.Timer1Timer(Sender: TObject);
begin
i:=i+1;
self.series1.Add(i);
end;


>>这是为什么?
你听我慢慢道来(我的意见)


你创建了一个Tform2 .

你的这个unit1 文件件应是下面这样子.(有可能有错误我随手写的)



unit unit2
uses
.............

type
tfrom2:=classs(form)
......
......
....

interface
.. ..........


procedure TForm2.Timer1Timer(Sender: TObject);
begin
i:=i+1;
self.series1.Add(i);
end;


要知道为什么 你要知道下面的这几个问题.
1.
tfrom2:=classs(form)
tform2 是类 tform 的子类. 继承了tform 的一切属性

2.
procedure TForm2.Timer1Timer(Sender: TObject);
begin
i:=i+1;
self.series1.Add(i);
end;
只是tform2 的一个方法表明 只了tform2 被创建了
它就有 这个方法.


3.
而你的 这名代码
form2:=tform2.create

的意思是 form2 只是 类tform2 的一个实例.
也就是说 form2 其实是一个变量. 更具体说它只是一指针.
它指向 由 tform2.create 分配的一段内存的首地址.
当然 tform2.create 后它会执行 tform2.timertimer
这个方法

明白了上面两面两点你就明白了为什么会出现你说的哪种现象了.

也就是你每一次点 form1.button1.click 时
都会创建 tform2 的一个实例.
而 form2 这个变量只是保存最后一个创建的实例的地址'
这就是为什么 你只能控制 最一个窗体的的原因.
因为你只有一个 变量form1 .
而上面提到的 方法 用数组 只是起到了定义多个变量 能控制多个创建的窗体而已.


>>我发现我第二次创建的form2里的series1也在
>>画线,只是数值马上会和我第一次创建的form2里的数值相等,这是为什么?
>>怎么样才能解决?就是说我创建的窗体是完全一样的,代码和功能是完全相同的
>>但是如何让他们互相不干扰?是继承吗?


这个问题其实也很好解决. 上面已有解决方法
这个问题基实是delphi 中的 问题
delphi 把 user 引用的单元 public 定义的变量 在其它单元中也可以使用引用
这就是 "友元"

其实这也解决了全局变量的问题

如果你要定义一个全局变量. 并且你的第统中多个unit 哪你一个在一个unit 中public 中定义一下
然后在其它 unit 中都引用一下就可以了

建义你看看相关的 delphi 方法的书箱 一秀般都有



今天心情好 一不小心就写了这么多 累了




 
既不是继承也不是重用
其实就是一个类的多个实例。
原先你的I是单元内全局变量,所以各个实例可以相互影响,如果你把I改成类的私有变量(
把它放在类里面定义),就不会互相影响了。 因为各个实例都有自己的变量区域。

你在实际应用中,如果不需要各实例间共享数据,就不要使用全局变量,也就不会在各个实
例中相互影响了。
 
哦,有点头绪了:)如果我不需要在多实例之间共享数据和互相干扰就不生明全局变量。
那我在timer里要画线,是不是要把procedure Timer1Timer(Sender: TObject);
放在private里?
 
顶部