你如何让一个类监听由其他类引起的PropertyChangeEvents,而不是这个类?

时间:2022-09-25 10:32:22

As described in another question, I have a set of Model objects and an associated set of Panel objects which allow the user to access the data in the Model objects. The Panels are registered as PropertyChangeListeners for the Models, such that if something else updates a value in a Model, it fires a PropertyChangeEvent, and the Panel receives it and knows to resync its values from the Model. (Currently I'm naively just updating all the values, but this could be made more intelligent to pull only the changed property.)

如另一个问题所述,我有一组Model对象和一组相关的Panel对象,允许用户访问Model对象中的数据。 Panel被注册为Models的PropertyChangeListeners,这样如果其他东西更新Model中的值,它会触发PropertyChangeEvent,Panel会接收它并知道从Model中重新同步它的值。 (目前我天真地只是更新所有值,但是这可以更加智能化以仅提取已更改的属性。)

All of this makes sense when a Model is updated by some arbitrary, unknown source, which does happen in my application. However, most often a Model's properties are set by the Panels themselves. In this case, now that I've hooked the Panels up as PropertyChangeListeners for the Models, my code is doing something that makes no sense: after the Panel updates the Model, the Panel receives a PropertyChangeEvent from the Model and pulls the same value from the Model that it originally sent to the Model in the first place. No update needs to occur, and it makes no design sense for this to happen.

当模型被某个任意的,未知的源更新时,所有这些都是有意义的,这在我的应用程序中确实发生。但是,大多数情况下,模型的属性由面板本身设置。在这种情况下,现在我已经将Panels作为Model的PropertyChangeListeners挂钩了,我的代码正在做一些没有意义的事情:在Panel更新Model之后,Panel从Model接收一个PropertyChangeEvent并从中获取相同的值它最初发送给模型的模型。不需要进行更新,并且没有任何设计意义。

So how do I register something as a PropertyChangeListener but then say "Don't notify me of PropertyChangeEvents when I am the source of them?" (Note that I can't answer this by calling PropertyChangeEvent.getSource(); it'll give me my Model, not the Panel that sent the value in the first place; there's no way to look at this and tell what changed the Property.)

那么我如何将一些东西注册为PropertyChangeListener,然后说“当我是它的来源时,不要通知我PropertyChangeEvents?” (请注意,我无法通过调用PropertyChangeEvent.getSource()来回答这个问题;它会给我我的模型,而不是首先发送值的Panel;没有办法看看这个并告诉我改变了什么属性。)

2 个解决方案

#1


In all reality, do you really care if you get that event fired back at you? It allows you to handle any times the Model is changed outside the Panel and there really isn't a lot of overhead involved in checking to see if you actually have to update the value.

在所有现实中,你是否真的在意你是否将事件发回给你?它允许您在Panel之外的任何时候处理模型,并且在检查您是否确实需要更新值时确实没有太多的开销。

The PropertyChangeEvent holds the property being changed as well as the old and new values. You can check each incoming event to see if the value in the Panel is the same as the new value, and if it is then discard that event. The Model should tell everyone that is listening to it for PropertyChangeEvents every time it has changed otherwise it will need to know too much about the Objects that are listening to it.

PropertyChangeEvent保存要更改的属性以及旧值和新值。您可以检查每个传入事件,以查看Panel中的值是否与新值相同,如果是,则丢弃该事件。模型应该告诉每个人每次更改时都会为​​PropertyChangeEvents监听它,否则它需要了解太多关于正在监听它的对象。

Whatever you do, DO NOT create property change event listener loops. You will end up with a situation that very easily can end in an infinite loop if you are not very careful.

无论你做什么,都不要创建属性更改事件侦听器循环。如果你不是很小心的话,你最终会遇到一个非常容易陷入无限循环的情况。

#2


I don't think that there is any measurable detriment by the unneccessary repaint during runtime. So from that point of view there's no need of changing the code. In that situation you should decide having regard to design/architecture. You say:

我不认为在运行时不必要的重绘有任何可衡量的损害。所以从这个角度来看,不需要改变代码。在这种情况下,您应该考虑设计/架构。你说:

...and it makes no design sense for this to happen...

......这对于这种情况没有任何设计意义......

, but it does! If you want to avoid the repaint, you have to add the source (the panel) to the parameters of the method(s) that change(s) the model, put it into the change event and consider that parameter when evaluating the event again, which makes your code much more complicated. Think what else you have to do, if there are two instances of the same panel, one that changes the model, one that has to be changed after receiving the event...adding object-ids to method calls...What if later changing the design of model or view the way that editing one field of the panel leads to changes of the model that are shown in another part of the panel - additional changes again...etc.

,但确实如此!如果要避免重绘,则必须将源(面板)添加到更改模型的方法的参数中,将其放入change事件并在再次评估事件时考虑该参数,这使你的代码更复杂。想想你还有什么需要做的,如果同一个面板有两个实例,一个更改模型,一个必须在收到事件后更改...添加对象-id到方法调用...如果以后怎么办?更改模型的设计或查看编辑面板的一个字段导致面板另一部分中显示的模型更改的方式 - 再次进行其他更改...等。

Moreover, if you would do as described, you'll break with the decoupling of model and view, which is never a good idea.

此外,如果您按照描述进行操作,您将打破模型和视图的分离,这绝不是一个好主意。

If you want to keep it simple, leave it as it is. The only reason to write complicated code is bad results during runtime and I don't think you'll get that.

如果您想保持简单,请保持原样。编写复杂代码的唯一原因是在运行时期间结果不好,我不认为你会得到它。

#1


In all reality, do you really care if you get that event fired back at you? It allows you to handle any times the Model is changed outside the Panel and there really isn't a lot of overhead involved in checking to see if you actually have to update the value.

在所有现实中,你是否真的在意你是否将事件发回给你?它允许您在Panel之外的任何时候处理模型,并且在检查您是否确实需要更新值时确实没有太多的开销。

The PropertyChangeEvent holds the property being changed as well as the old and new values. You can check each incoming event to see if the value in the Panel is the same as the new value, and if it is then discard that event. The Model should tell everyone that is listening to it for PropertyChangeEvents every time it has changed otherwise it will need to know too much about the Objects that are listening to it.

PropertyChangeEvent保存要更改的属性以及旧值和新值。您可以检查每个传入事件,以查看Panel中的值是否与新值相同,如果是,则丢弃该事件。模型应该告诉每个人每次更改时都会为​​PropertyChangeEvents监听它,否则它需要了解太多关于正在监听它的对象。

Whatever you do, DO NOT create property change event listener loops. You will end up with a situation that very easily can end in an infinite loop if you are not very careful.

无论你做什么,都不要创建属性更改事件侦听器循环。如果你不是很小心的话,你最终会遇到一个非常容易陷入无限循环的情况。

#2


I don't think that there is any measurable detriment by the unneccessary repaint during runtime. So from that point of view there's no need of changing the code. In that situation you should decide having regard to design/architecture. You say:

我不认为在运行时不必要的重绘有任何可衡量的损害。所以从这个角度来看,不需要改变代码。在这种情况下,您应该考虑设计/架构。你说:

...and it makes no design sense for this to happen...

......这对于这种情况没有任何设计意义......

, but it does! If you want to avoid the repaint, you have to add the source (the panel) to the parameters of the method(s) that change(s) the model, put it into the change event and consider that parameter when evaluating the event again, which makes your code much more complicated. Think what else you have to do, if there are two instances of the same panel, one that changes the model, one that has to be changed after receiving the event...adding object-ids to method calls...What if later changing the design of model or view the way that editing one field of the panel leads to changes of the model that are shown in another part of the panel - additional changes again...etc.

,但确实如此!如果要避免重绘,则必须将源(面板)添加到更改模型的方法的参数中,将其放入change事件并在再次评估事件时考虑该参数,这使你的代码更复杂。想想你还有什么需要做的,如果同一个面板有两个实例,一个更改模型,一个必须在收到事件后更改...添加对象-id到方法调用...如果以后怎么办?更改模型的设计或查看编辑面板的一个字段导致面板另一部分中显示的模型更改的方式 - 再次进行其他更改...等。

Moreover, if you would do as described, you'll break with the decoupling of model and view, which is never a good idea.

此外,如果您按照描述进行操作,您将打破模型和视图的分离,这绝不是一个好主意。

If you want to keep it simple, leave it as it is. The only reason to write complicated code is bad results during runtime and I don't think you'll get that.

如果您想保持简单,请保持原样。编写复杂代码的唯一原因是在运行时期间结果不好,我不认为你会得到它。