【问题标题】:How to correctly put a dialog inside animation timer in JavaFX如何在 JavaFX 中正确地将对话框放入动画计时器中
【发布时间】:2017-03-30 14:36:55
【问题描述】:

我有一个动画计时器,当我处理结束时,如果某个条件为真,我想向用户显示一个对话框。当我只是尝试在 stop() 方法之后调用对话框时,我遇到了这个异常(仅在移动设备上):

java.lang.IllegalStateException:在动画或布局处理期间无法进入嵌套循环

因此,对于这种情况,我解决了将对话框包装在 Platform.runLater() 方法中的问题。

这是处理这种情况的正确方法吗?

如果不是,哪个是正确的?

我使用的对话框是胶子对话框:

http://docs.gluonhq.com/charm/javadoc/4.2.0/com/gluonhq/charm/glisten/control/Dialog.html

而且在这个简单的表演中不存在,只有表演和等待。

【问题讨论】:

  • 我假设你打电话给showAndWait()。根据documentation(参见@throws 部分),这只能在事件处理程序中调用。看来您可以在Platform.runLater(...) 中调用它,但这没有明确记录在AFAIK 中。你能打电话给show()吗?
  • show() 在胶子对话框中不存在。还有其他建议吗?
  • 哦,这是 Gluon 对话框,而不是标准的 JavaFX 对话框?不知道,我根本没有处理过。
  • 是的,对不起,我的错误。下次我会更具体的

标签: java javafx java-8 gluon gluon-mobile


【解决方案1】:

我在AnimationTimer 中添加了Alert 以重现该问题:

private long count = 0;

public BasicView(String name) {
    super(name);

    AnimationTimer timer = new AnimationTimer() {
        private long time;

        @Override
        public void handle(long now) {
            if (now - time > 1_000_000_000) {
                count++;
                if (count == 5) {
                    Alert alert = new Alert(Alert.AlertType.INFORMATION, "Hi there");
                    alert.showAndWait();
                }
                time = now;
            }

        }
    };

    setCenter(new StackPane(new Label("Hello JavaFX World!")));

    setOnShown(e -> timer.start());
    setOnHidden(e -> timer.stop());
}

无论你选择javafx.scene.control.Alert,都会失败:

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: showAndWait is not allowed during animation or layout processing
at javafx.scene.control.Dialog.showAndWait(Dialog.java:328)

com.gluonhq.charm.glisten.control.Alert:

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Cannot enter nested loop during animation or layout processing
at com.sun.javafx.tk.quantum.QuantumToolkit.enterNestedEventLoop(QuantumToolkit.java:570)
at com.gluonhq.charm.glisten.control.Dialog.a(SourceFile:613)

以及您是在桌面还是 Android 上运行它:

04-05 17:50:48.289  9592  9627 E AndroidRuntime: java.lang.IllegalStateException: Cannot enter nested loop during animation or layout processing
04-05 17:50:48.289  9592  9627 E AndroidRuntime:    at com.sun.javafx.tk.quantum.QuantumToolkit.enterNestedEventLoop(QuantumToolkit.java:585)
04-05 17:50:48.289  9592  9627 E AndroidRuntime:    at com.gluonhq.charm.glisten.control.Dialog.a(SourceFile:613)

Dialog 实现 (JavaFX/Gluon) 使用 Toolkit.getToolkit().enterNestedEventLoop(),如果您检查 Quantum implementation

if (!canStartNestedEventLoop()) {
    throw new IllegalStateException("Cannot enter nested loop during animation or layout processing");
}

如果你在动画中尝试这个:

@Override
public void handle(long now) {
    System.out.println("In pulse: " + !Toolkit.getToolkit().canStartNestedEventLoop()); 
}

您将在动画中看到您的脉搏是真实的:根据 animationTimer 的定义,handle 在每个脉搏上都被精确调用!

所以你不能进入一个嵌套的事件循环,除非你在那个瞬间避免调用。 Platform.runLater() 这只是稍后的一种方式。

所以这会正常工作:

@Override
public void handle(long now) {
        if (now - time > 1_000_000_000) {
            count++;
            if (count == 5) {
                Alert alert = new Alert(AlertType.INFORMATION, "Hi there");
                Platform.runLater(alert::showAndWait);
            }
            time = now;
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 2015-07-06
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    相关资源
    最近更新 更多