简体   繁体   English

如何从非JavaFX线程调用JavaFX控制器并等待GUI更改完成(播放视频结束)?

[英]How to call JavaFX controller from non JavaFX thread and wait for the GUI changes to finish (finish playing video)?

I have 2 classes: Controller ( JavaFX controller) and MachineController (not JavaFX thread). 我有2类: ControllerJavaFX控制器)和MachineController (不是JavaFX线程)。 Sometimes MachineController sent message to Controller using method setMessage . 有时MachineController使用setMessage方法将消息发送到Controller

Method setMessage(String str) should update GUI by adding String to the List and on the Label , also if it is necessary, I shoul play the video or show Images, but i must wait for end of playing video or end of showing Image (it shows some time (for example, 3-4 seconds)). setMessage(String str)应通过将String添加到ListLabel setMessage(String str)更新GUI,如果有必要,我也应该播放视频或显示图像,但是我必须等待视频播放结束或图像显示结束(它显示一些时间(例如3-4秒)。

I have used Task and Platform.runLater() . 我已经使用TaskPlatform.runLater() But if i use Task Images are shown only sometimes, and video wasn't played at all. 但是,如果我使用“ Task图像”,则仅在某些时候显示,而根本没有播放视频。 If i use Platform.runLater i couldn't wait to end of playing video or shoeing image, because it start in the futere. 如果我使用Platform.runLater我将迫不及待想要播放视频或启动图像,因为它始于futere。

Controller 调节器

public void setMessage(final String str) {

    Task<Void> task = new Task<>() {
        boolean test = true;
        @Override
        protected Void call() throws Exception {
            while (test) {
                currentCommandLabel.setText(str);
                commands.add(str);
                Executable show = analyze.getExec(str);
                show.exec(pane);
                Thread.sleep(1000);
            }
            return null;
        }
    };

    Thread thread = new Thread(task);
    thread.start();
    try {
        thread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Executable 可执行文件

interface Executable {
    void exec(GridPane pane);
}

Analize Analize

Executable getExec(String string) {
    return panel -> {
                cleanZeroCell(pane1);
                File fileImage = new File("<path to image file>");
                Image image = new Image(fileImage.toURI().toString());
                imageView.setImage(image);
                panel.add(imageView, 0, 0);
            };
}

Also I have tried to used setMessage like this: 我也尝试过使用setMessage这样的:

public void setMessage(final String str) {
    Platform.runLater(() -> {
        currentCommandLabel.setText(str);
        commands.add(str);
    });
    Executable show = analyze.getExec(str);
    Platform.runLater(() -> show.exec(pane));
}

You can use a CountDownLatch to wait for the JavaFX application thread on a non-application thread. 您可以使用CountDownLatch在非应用程序线程上等待JavaFX应用程序线程。 The following example uses a animation instead of a video or "image showing", but you could easily use the MediaPlayer.onEndOfMedia event instead of Animation.onFinished event: 下面的示例使用动画而不是视频或“图像显示”,但是您可以轻松地使用MediaPlayer.onEndOfMedia事件而不是Animation.onFinished事件:

private void startAnimation(Button button, CountDownLatch latch) {
    TranslateTransition animation = new TranslateTransition(Duration.seconds(2), button);
    animation.setByX(100);
    animation.setOnFinished(evt -> latch.countDown());
    animation.play();
}

@Override
public void start(Stage primaryStage) {
    Button btn = new Button("Animate");
    btn.setOnAction((ActionEvent event) -> {
        new Thread(() -> {
            try {
                // simulates some work prior to modifying the ui
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
            }

            CountDownLatch latch = new CountDownLatch(1);
            // start animation on application thread
            Platform.runLater(() -> startAnimation(btn, latch));
            try {
                // wait for application thread to count down the latch
                latch.await();
                System.out.println("Done");
            } catch (InterruptedException ex) {
                ex.printStackTrace(System.err);
            }

        }).start();
    });

    StackPane root = new StackPane();
    root.getChildren().add(btn);

    Scene scene = new Scene(root, 200, 200);

    primaryStage.setScene(scene);
    primaryStage.show();
}

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

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