我在JavaFx WebView中从JavaScript调用Java方法。 Java方法可以完成一些工作,即不会立即返回。等待该方法从JavaScript完成的自然方式是什么?
答案 0 :(得分:1)
由于所有内容都在FX Application Thread上执行,因此您调用的Java方法需要在后台线程上运行长时间运行的进程(否则您将使UI无响应)。您可以将方法传递给Javascript函数,以便在完成时调用:请注意,需要在FX Application Thread上调用此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&lt; - &gt; Java通信的专家,但这对我来说似乎没问题。)