我想知道接收回调/事件时“常规”Java应用程序是否常见以下内容。这些回调可以由用户输入触发,也可以通过其他方式触发,因此它不仅与UI事件有关:
public void handleEvent( @NotNull final SomeEvent e ) {
final boolean process;
synchronized ( this ) {
process = !e.equals(filter);
filter = e;
}
if ( process ) {
...
}
}
基本上在一些复杂的方案下(非常复杂的UI涉及同一模型的几个视图,用户可以从不同的屏幕修改模型[如复杂的3D程序])我有很多事件被解雇,我已经注意到我可以使用上面的代码片段过滤掉重复的事件。如果事件已处理且下一个事件与上次处理的事件完全相同(保存在filter
引用中),则简单地忽略事件/回调。
工作正常。我想知道过滤重复事件是否是一种常见的技术?
答案 0 :(得分:2)
并非总是如此,但通常这可能表明事件级联链的某些元素未正确检测到它们不需要发送事件。经典插图是一个bean设置器,即使值没有改变也会生成一个PropertyChangeEvent。
虽然您所做的事情将会过滤掉这些事件,但它并没有解决可能存在的基本问题。
问题是这些“错误”可以组合形成无限循环。扩展上面的bean示例,假设您有一个UI根据该bean字段重置其可编辑值...并且重置UI值也将调用bean设置器,因为那里也没有进行正确的欺骗检查。第一次编辑该值并发生无限循环。
这些示例在发生时很明显,但随着通知层次结构变得越来越复杂,跟踪这些事情变得更加困难,并且可能会在更多间歇性时间发生。
一个好的经验法则是让每个事件生成组件尽可能保守。在事件(heh)中,您正在接收来自您无法控制的组件的通知,并且将转发您自己的事件,然后像您设置的过滤器可能是阻止潜在更大的扩散的唯一选项问题不仅仅是表现。
答案 1 :(得分:1)
我唯一能想到的是基于选择是否仍在变化(即用户仍在点击并拖动鼠标)或者事件是否代表“最终”选择事件而在ListSelectionEvent
上进行操作; e.g。
public class MyListSelectionListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent evt) {
// Finished selecting
if (!evt.getValueIsAdjusting()) {
JOptionPane.showMessageDialog("Selection Complete!");
}
}
}
答案 2 :(得分:1)
看起来你可能有一个监听器两次注册到同一个源。这可能会导致它。或者您可能已在多个实例中注册了一个侦听器。如果您看到了陌生感,请寻找无限的事件循环,不幸的是,由于Swing程序自行组织的方式,可能很容易发生。你想要将这些听众分开。
我从来没有做过这种事情或遇到过它。正如有些人指出某些控件会在调整选择时触发事件,但有一些方法可以过滤掉这些事情。
同步(this)块也是可疑的,因为你总是会在Swing线程上回调。如果你的程序中不是这样,那么你违反了Swing的线程规则,这可以解释问题。底线是你不需要synchronized块,因为Swing是单线程的。
(我假设这是Swing,就像其他一些海报一样,但仅从你的代码来看它是模棱两可的。)