gpt4 book ai didi

java - 尝试清除 JavaFX ObservableMap 时出现 ConcurrentException

转载 作者:行者123 更新时间:2023-11-29 05:22:59 25 4
gpt4 key购买 nike

我正在向我的 JavaFX 8 应用程序添加一些加速器,当我尝试清除场景的加速器时,我遇到了 ConcurrentModificationException。让我解释一下,而不是为每个对话框使用一个场景,我创建了一个伪对话框,它只是一个带有覆盖的 Pane 。添加 Pane 时,将删除旧 Pane 的加速器并添加新 Pane 的加速器。当对话框关闭时,旧的加速器将恢复:

public abstract class DialogController{

private Map<KeyCombination, Runnable> accelerators;
.
.
.

protected final void loadMainPane() throws IOException {
.
.
.
pane.sceneProperty().addListener(new ChangeListener<Scene>() {
@Override
public void changed(ObservableValue<? extends Scene> observableValue, Scene oldScene, Scene newScene) {
if (newScene != null)
enableAccelerators();
else
disableAccelerators(oldScene);
}
});
}

protected void enableAccelerators() {
accelerators = new HashMap<KeyCombination, Runnable>(pane.getScene().getAccelerators());
pane.getScene().getAccelerators().clear();
pane.getScene().getAccelerators().put(new KeyCodeCombination(KeyCode.ENTER, KeyCombination.ALT_DOWN), new Runnable() {
@Override
public void run() {
submit(null);
}
});
}

protected void disableAccelerators(Scene scene) {
scene.getAccelerators().putAll(accelerators);
}
}

当子类需要添加新的加速器时,他们只需要覆盖 enableAccelerators() 方法,调用 super 并添加所需的新加速器。但是,有时,当 enableAccelerators 尝试清除场景的加速器时,会抛出此异常:

java.util.ConcurrentModificationException: null
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
at java.util.HashMap$EntryIterator.next(HashMap.java:1463)
at java.util.HashMap$EntryIterator.next(HashMap.java:1461)
at com.sun.javafx.collections.ObservableMapWrapper$ObservableEntrySet$1.next(ObservableMapWrapper.java:588)
at com.sun.javafx.collections.ObservableMapWrapper$ObservableEntrySet$1.next(ObservableMapWrapper.java:576)
at com.sun.javafx.scene.KeyboardShortcutsHandler.processAccelerators(KeyboardShortcutsHandler.java:340)
at com.sun.javafx.scene.KeyboardShortcutsHandler.dispatchBubblingEvent(KeyboardShortcutsHandler.java:168)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:204)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3949)
at javafx.scene.Scene$KeyHandler.access$2100(Scene.java:3896)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2036)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2493)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:170)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:123)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:197)
at com.sun.glass.ui.View.handleKeyEvent(View.java:517)
at com.sun.glass.ui.View.notifyKey(View.java:927)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.access$200(GtkApplication.java:48)
at com.sun.glass.ui.gtk.GtkApplication$6$1.run(GtkApplication.java:149)
at java.lang.Thread.run(Thread.java:745)

我怀疑我的代码正在清除加速器,而 JavaFX 正在迭代它。我尝试将清除部分放在同步块(synchronized block)中,但它不起作用:

protected void enableAccelerators() {
accelerators = new HashMap<KeyCombination, Runnable>(pane.getScene().getAccelerators());
synchronized (pane.getScene().getAccelerators()){
pane.getScene().getAccelerators().clear();
}
pane.getScene().getAccelerators().put(new KeyCodeCombination(KeyCode.ENTER, KeyCombination.ALT_DOWN), new Runnable() {
@Override
public void run() {
submit(null);
}
});
}

如何避免这个问题?

最佳答案

您可能需要将更新加速器的代码放入 Platform.runLater() 调用中。尝试

        public void changed(ObservableValue<? extends Scene> observableValue, Scene oldScene, Scene newScene) {
Platform.runLater(() -> {
if (newScene != null)
enableAccelerators();
else
disableAccelerators(oldScene);
});
}

如果 FX 应用程序线程在处理事件时调用您的代码,那么可以想象(如您所建议的)它会在迭代加速器集合时这样做。使用 Platform.runLater() 将导致您的代码在处理完 FX 应用程序线程上当前挂起的任何内容后执行。

(如果这看起来有点像 hack,好吧,被指控有罪......)

关于java - 尝试清除 JavaFX ObservableMap 时出现 ConcurrentException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23934095/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com