简体   繁体   English

如何避免Swing中的无限更新循环?

[英]How to avoid infinite update loops in Swing?

I have a JPanel with a set of items (for example combo boxes and text fields). 我有一个带有一组项目的JPanel(例如组合框和文本字段)。 Some action listeners are implemented on those items to register user updates. 在这些项目上实现了一些动作侦听器以注册用户更新。

If the user selects a value in a JComboBox (for example), the action listener captures the event. 如果用户在JComboBox中选择一个值(例如),则动作侦听器捕获该事件。 The corresponding underlying bean method is called and the panel is refreshed. 调用相应的底层bean方法并刷新面板。 Changing can have an impact on other fields displayed in the pane. 更改可能会对窗格中显示的其他字段产生影响。

The problem is that when the panel is refreshed, all listeners are triggered, and they call for a refresh themselves. 问题是当刷新面板时,会触发所有侦听器,并且他们自己要求刷新。 This leads to an infinite loop. 这导致无限循环。

How can I avoid this? 我怎么能避免这个? I can't get rid of the listeners, because I need to capture user updates, but I don't want these to fire when I am only refreshing the panel content. 我无法摆脱听众,因为我需要捕获用户更新,但是当我只刷新面板内容时,我不希望这些更新。

One option is to have a central boolean value or some indicator that each listener can check to prevent the chaining of events. 一种选择是具有中心布尔值或一些指示符,每个侦听器可以检查以防止事件的链接。

Another option is to not refresh the field if the value does not change. 另一个选择是如果值没有改变则不刷新字段。 That way each component is updated at most once per refresh. 这样每个组件每次刷新最多更新一次。

I can't get rid of the listeners, because I need to capture user updates, but I don't want these to fire when I am only refreshing the pane content 我无法摆脱听众,因为我需要捕获用户更新,但是当我只刷新窗格内容时,我不希望这些更新

Then remove the listeners, refresh the pane content and then restore the listeners. 然后删除侦听器,刷新窗格内容,然后还原侦听器。 This way the listeners only fire when a user change is made. 这样,只有在进行用户更改时才会触发侦听器。

I think that if your problem is in combobox it just points to a bug. 我认为,如果你的问题是在组合框中,它只是指向一个错误。 Really, if user changes the value of the combobox, that somehow triggers refresh of the pane the value of the combo box should not be changed second time! 真的,如果用户更改组合框的值,以某种方式触发窗格的刷新,组合框的值不应该第二次更改! So if it is onValueChanged() (or something like this) it should not be called at all when pane is being refreshed. 因此,如果它是onValueChanged()(或类似的东西),则在刷新窗格时根本不应该调用它。

But if for some reason it happens you can verify whether the old and new values are the same and exit the listener. 但是如果出于某种原因它可以验证旧值和新值是否相同并退出侦听器。

If this still does not help I'd suggest you some non-standard solution: try to investigate the stack trace into the listener. 如果这仍然没有帮助,我会建议你一些非标准的解决方案:尝试调查堆栈跟踪到监听器。 Can you identify whether the listener was called as a direct reaction to user's action or after the pane refresh? 您能否确定是否将监听器作为对用户操作的直接反应或在窗格刷新后进行调用? In this case you can create utility method and put it in the beginning of all relevant listeners. 在这种情况下,您可以创建实用程序方法并将其放在所有相关侦听器的开头。

My applications also suffered from this problem, and solution with the flag, that I should check in every listener and enable/disable in code, feels not very good for me. 我的应用程序也遇到了这个问题,带有标志的解决方案,我应该检查每个监听器并启用/禁用代码,对我来说感觉不是很好。 I always forgot to set this flag to true/false in necessary places. 我总是忘记在必要的地方将此标志设置为true / false。 That is why I decide to implement another solution. 这就是我决定实施另一种解决方案的原因。 I just subclass all default swing components that I am using often, and implemented custom ValueChanged event that I fire after mouse/keyboard/clipboard/etc events. 我只是将我经常使用的所有默认swing组件子类化,并实现了我在鼠标/键盘/剪贴板/ etc事件后触发的自定义ValueChanged事件。 Now I am always know, that if ValueChanged event is fired, it means, that value was issued by user, not by code. 现在我总是知道,如果触发了ValueChanged事件,则意味着该值是由用户发出的,而不是由代码发出的。 Event handling in this way much more cleaner. 事件处理以这种方式更加清洁。 This solution solves my problem. 这个解决方案解决了我的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM