简体   繁体   English

如何在JavaFX中的动画计时器中正确放置对话框

[英]How to correctly put a dialog inside animation timer in JavaFX

I have an animation timer and when i handle the end, if a certain condition is true, i want to show a dialog to the user. 我有一个动画计时器,当结束处理时,如果满足特定条件,我想向用户显示一个对话框。 When i simply tried to call the dialog after the stop() method i had this exception (only on mobile): 当我只是尝试在stop()方法之后调用对话框时,出现了此异常(仅在移动设备上):

java.lang.IllegalStateException: Cannot enter nested loop during animation or layout processing java.lang.IllegalStateException:在动画或布局处理期间无法进入嵌套循环

So, for this case, i solved it wrapping the dialog inside Platform.runLater() method. 因此,对于这种情况,我解决了将对话框包装在Platform.runLater()方法内的问题。

Is this the correct way to handle this case? 这是处理这种情况的正确方法吗?

If not, which is the correct one? 如果不是,哪一种是正确的?

The dialog i'm using is gluon dialog: 我正在使用的对话框是胶粘剂对话框:

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

And on this simply show doesn't exist, there's only show and wait. 在这个简单的表演上不存在,只有表演和等待。

I've added an Alert inside an AnimationTimer to reproduce the issue: 我在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());
}

This fails whether you choose javafx.scene.control.Alert : 无论您选择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)

or com.gluonhq.charm.glisten.control.Alert : 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)

and whether you run it on desktop or Android: 以及您是在台式机还是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)

The Dialog implementation (JavaFX/Gluon) makes use of Toolkit.getToolkit().enterNestedEventLoop() , and if you check the Quantum implementation : Dialog实现(JavaFX / Gluon)使用Toolkit.getToolkit().enterNestedEventLoop() ,如果您检查了Quantum 实现,则

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

If you try this inside the animation: 如果您在动画中尝试此操作:

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

you will see that inside the animation your pulse is true: by definition of an animationTimer, handle is called precisely on every pulse! 您会看到在动画中您的脉搏是真实的:根据animationTimer的定义,在每个脉搏上都会精确调用handle

So you can't enter a nested event loop, unless you avoid the call on that instant. 因此,除非您避免在该瞬间调用,否则您将无法进入嵌套事件循环。 Platform.runLater() it's just a way to do it a little bit later . Platform.runLater()只是稍后再做的一种方法。

So this will work fine: 所以这可以正常工作:

@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;
        }
}

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

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