javascript - JavaFx WebView 等待 Java 方法完成

标签 javascript multithreading asynchronous javafx webview

我正在 JavaFx WebView 中从 JavaScript 调用 Java 方法。 Java 方法做了一些工作,即不会立即返回。等待 JavaScript 方法完成的自然方法是什么?

最佳答案

由于所有内容都在 FX 应用程序线程上执行,因此您调用的 Java 方法需要在后台线程上运行长时间运行的进程(否则您将使 UI 无响应)。您可以向该方法传递一个 Javascript 函数以在完成时调用:请注意,需要在 FX 应用程序线程上调用此 javascript 函数。一种方法是将调用包装在 Platform.runLater() 中,但使用 Task 会使事情变得更清晰。

这是一个 SSCCE:

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;

public class WebViewCallbackTest extends Application {

    private static final String HTML = 
              "<html>"
            + "  <head>"
            + "    <script>"
            + ""
            + "      function doCall() {"
            + "         javaApp.doLongRunningCall('updateResults');"
            + "      }"
            + ""
            + "      function updateResults(results) {"
            + "         document.getElementById('results').innerHTML = results ;"
            + "      }"
            + ""
            + "    </script>"
            + "  </head>"
            + "  <body>"
            + "    <div>"
            + "      Result of call:"
            + "    </div>"
            + "    <div id='results'></div>"
            + "  </body>"
            + "</html>";

    private Button button;

    private JSObject window;

    @Override
    public void start(Stage primaryStage) {
        WebView webView = new WebView();
        webView.getEngine().loadContent(HTML);

        BorderPane root = new BorderPane(webView);

        window = (JSObject) webView.getEngine().executeScript("window");
        window.setMember("javaApp", this);


        button = new Button("Run process");
        button.setOnAction(e -> webView.getEngine().executeScript("doCall()"));

        HBox controls = new HBox(button);
        controls.setAlignment(Pos.CENTER);
        controls.setPadding(new Insets(5));
        root.setBottom(controls);

        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public void doLongRunningCall(String callback) {
        Task<String> task = new Task<String>() {
            @Override
            public String call() throws InterruptedException {
                Thread.sleep(2000);
                return "The answer is 42";
            }
        };

        task.setOnSucceeded(e -> 
            window.call(callback, task.getValue()));
        task.setOnFailed(e -> 
            window.call(callback, "An error occurred"));

        button.disableProperty().bind(task.runningProperty());

        new Thread(task).start();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

(可能有比这更简单的方法:我不是 Webview Javascript <-> Java 通信方面的专家,但这对我来说似乎没问题。)

关于javascript - JavaFx WebView 等待 Java 方法完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42545000/

相关文章:

javascript - 如何将函数的 "this"绑定(bind)到类(React 组件)

java - 如何在不是线程的对象上调用wait()和notify()方法?

c - 声明 'volatile' 数据类型供线程使用

multithreading - 如何在多线程程序上启用反向调试?

javascript - window.addEventListener ("load",function() 是否比放置在页面底部的 &lt;script&gt; 更快?

php - 在我的页面上显示用户输入

javascript - 使用 koa 2 和 mongoose 进行异步/等待

ios - "Request failed: unacceptable content-type: text/html"使用 AFNetworking 2.0

vb.net - vb.net 回调中的错误处理

javascript - 在对话框上显示数据而无需重新加载页面