读书人

自动计算字段引起死循环的有关问题

发布时间: 2012-03-31 13:13:26 作者: rapoo

自动计算字段引起死循环的问题
记录集有三个字段 price单价、amout数量、charge金额,记录集的locktype属性为ltBatchOptimistic
单价或数量改变时,自动计算金额 charge:=amount*price;
金额改变时,自动计算单价 price:=charge/amount;

问题:单价或数量改变时,计算出金额,给金额赋值,这时候,金额发生改变,触发金额自段的onchange事件,在onchange事件中开始计算单价,然后给单价赋值,又触发单价的onchange事件(虽然这时赋给单价的值跟上次输入的值一致,但确实引发了单价的onchange事件),这样就导致了死循环。

大家有什么好的解决方法呢?

Delphi(Pascal) code
procedure TForm1.qry1priceChange(Sender: TField);var  price,amount,charger:Real;begin  price:=Sender.DataSet.FieldByName('price').AsFloat;  amount:=Sender.DataSet.FieldByName('amount').AsFloat;  charge:=price*amount;  if charge<>0 then Sender.DataSet.FieldByName('charge').AsFloat:=charge;end;procedure TForm1.qry1amountChange(Sender: TField);var  price,amount,charger:Real;begin  price:=Sender.DataSet.FieldByName('price').AsFloat;  amount:=Sender.DataSet.FieldByName('amount').AsFloat;  charge:=price*amount;  if charge<>0 then Sender.DataSet.FieldByName('charge').AsFloat:=charge;end;procedure TForm1.qry1chargeChange(Sender: TField);var  price,amount,charger:Real;begin  amount:=Sender.DataSet.FieldByName('amount').AsFloat;  charge:=Sender.DataSet.FieldByName('charge').AsFloat;  if amount<>0 then price:=charge/amount else exit;  Sender.DataSet.FieldByName('price').AsFloat:=price;end;


[解决办法]
定义一个bo:Boolean全局变量做标记
当前onChange事件赋值前为bo:=True,赋值后bo:=False
其它onChange事件判断是bo,为True的时候就跳过

或者这样,赋值前设置其它的onChange无效,赋值后变回来,如在price的Change事件:
//bo:=True;
qry1.FieldByName('charge').onChange:=nil;
..赋值..
qry1.FieldByName('charge').onChange:=qry1chargeChange;
//bo:=False;



[解决办法]
高手出手了呀
[解决办法]
简单的说,在onChange事件中加判断,不是每次Change就触发代码即可。
嘿嘿。站着说话不腰疼,可耻的飘过。。。

探讨
定义一个bo:Boolean全局变量做标记
当前onChange事件赋值前为bo:=True,赋值后bo:=False
其它onChange事件判断是bo,为True的时候就跳过

或者这样,赋值前设置其它的onChange无效,赋值后变回来,如在price的Change事件:
//bo:=True;
qry1.FieldByName('charge').onChange:=nil;
……

[解决办法]
又见旺旺贝贝呀,在ONEXIT事件中添加这些代码是否也可行呢?

ONEXIT比较值是否已改变或者不比较也行
[解决办法]
学习中

[解决办法]
统一在DATASOURCE的ONSTATECHANGE事件中做也应该可以,但是还是得定义全局变量,
[解决办法]
数据库侧写触发器,呵呵
[解决办法]
加上是否相同的判断(相同则不需要修改)
if (charge<>0) and (Sender.DataSet.FieldByName('charge').AsFloat<>charge) then
Sender.DataSet.FieldByName('charge').AsFloat:=charge;

3个地方都要加
另外要注意浮点的不等于比较
[解决办法]
探讨
加上是否相同的判断(相同则不需要修改)
if (charge<>0) and (Sender.DataSet.FieldByName('charge').AsFloat<>charge) then
Sender.DataSet.FieldByName('charge').AsFloat:=charge;

3个地方都要加
另外要注意浮点的不等于比较

[解决办法]

读书人网 >.NET

热点推荐