在Java中处理循环事件的优雅方式? [英] The Elegant way to handle Cyclic Event in Java?

查看:187
本文介绍了在Java中处理循环事件的优雅方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这不是我的具体问题;大家以前可能会遇到这个问题。
为了正确说明它,这里有一个简单的UI:



alt text http://www.freeimagehosting.net/uploads/7aec06ea46.png



如你所见,那两个纺纱商正在控制单个变量 - A。唯一的区别是它们使用不同的视图来控制它。



由于这两个旋转器的显示值是同步的,所以循环事件显示。



如果我更改顶部微调框,A将被更改,底部旋转框的值也将相应更新。 然而,更新底部旋转器的调用(例如setValue)也将触发另一个事件,指示顶部微调器根据底部微调器的值进行更新。因此,创建一个坏的循环,最终可能导致StackOverFlow异常。



我以前的解决方案有点麻烦:我放置了一个保护布尔值来指示是否第二次更新调用应该执行



现在我想问我如何优雅地处理这种情况?一般而言,不是特定于纺纱师



thx



< >

更新:



由于我有2个答案建议我使用观察器结构,我必须说一些关于



像我说的一样,这是伟大的,但远非完美。不仅因为其固有的复杂性,而且还因为无法解决问题。



为什么?要了解原因,您必须在Java Swing中实现View和Model-Controller的紧耦合。让我的微调UI为例。假设变量A实际上是一个Observer对象。然后,在从顶部旋转器触发第一个状态更改事件之后,ObserverA将更新其值并触发PropertyChange事件以通知底部旋转器。然后第二次更新更新底部微调器的视图。 但是,更改底部微调框的视图不可避免地触发一个冗余事件,将尝试再次设置A的值。之后,致命的循环是完全构建的,堆栈溢出将被抛出。



理论上,Observer模型试图通过引入2个独立的反馈路径来解决直接循环。链接的更新赔率(事件响应代码)隐式地形成连接两条路径的桥,再次进行循环。

解决方案

回到Model-View-Controller,想想你的Model是什么,你的View是什么。



在你目前的实现中,你有两个模型(每个Spinner一个控制),并且它们正在通过View层同步。



您应该做的是共享相同的后台模型。对于带有减法值的微调框,请为原始模型创建一个代理。即:

  class ProxySpinnerModel实现SpinnerModel {
getValue(){return originalSpinner.getValue() - 10}
setValue(v){originalSpinner.setValue(v + 10)}
}

spinnerA = new JSpinner()
spinnerB = new JSpinner(new ProxySpinnerModel(spinnerA.getModel ()))

现在,您不需要添加监听器,因为它们都工作关闭相同的模型,默认实现(originalModel)已经有更改监听器,它触发视图。


i think this not a specific problem to me; everybody might have encountered this issue before. To properly illustrate it, here's a simple UI:

alt text http://www.freeimagehosting.net/uploads/7aec06ea46.png

As you can see, those two spinners are controlling a single variable -- "A". The only difference is that they control it using different views.

Since these two spinners' displaying values are synchronized, cyclic event shows up.

If i change the top spinner, "A" will be changed and the bottom spinner's value will also be updated accordingly. However, updating the bottom spinner's call (such as setValue) will also trigger another event instructing the top spinner to update based on the bottom spinner's value. Thus creates a bad cycle which can eventually cause a StackOverFlow exception.

My previously solution is kinda cumbersome: i placed a guarding boolean to indicate whether the 2nd updating call should be performed.

Now i'd like to ask "how can i handle such situation elegantly? ( in general, not specific to spinners )"

thx


Update:

Since i've got 2 answers suggesting me to utilize the observer structure, i have to say something about it.

Like what i've said, it's great but far from being perfect. Not only because of its inherent complexity, but also Its inability to solve the problem.

Why? To see the reason, you must realize the tight coupling of the View and Model-Controller in Java Swing. Lets take my spinner UI for an example. Suppose the variable A is actually an Observer object. Then, after firing the first state change event from the top spinner, the Observer "A" will update its value and fire a PropertyChange event to notify the bottom spinner. Then comes the 2nd updating which updates the bottom spinner's View. However, changing bottom spinner's view inevitably triggers a redundant event that will try to set "A"'s value again. Afterwards, the deadly loop is fully constructed and the stack overflow will be thrown.

In theory, the Observer model tries to solve the direct cycle by introducing 2 independent feedback paths. The chained updating odds(in event-response codes) implicitly form a bridge connecting both paths, making a cycle again.

解决方案

Going back to Model-View-Controller, think about what your Model is, and what your View is.

In your current implementation, you have two models (one for each Spinner control), and they're being synced through the View layer.

What you should be doing though is share the same backing model. For the spinner with a subtracted value, create a proxy to the original model. ie:

class ProxySpinnerModel implements SpinnerModel {
    getValue() { return originalSpinner.getValue() - 10 }
    setValue(v) { originalSpinner.setValue(v+10) }
}

spinnerA = new JSpinner()
spinnerB = new JSpinner( new ProxySpinnerModel( spinnerA.getModel() ) )

Now, you don't need to add listeners, since they're both working off the same model and the default implementation (the originalModel) already has change listeners which it fires to the view.

这篇关于在Java中处理循环事件的优雅方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆