2017-03-02 74 views

回答

0

因为一切都在FX应用程序线程执行,你需要调用Java方法运行在后台线程长期运行过程中(否则你将会使UI反应迟钝)。您可以在JavaScript函数完成时调用该方法来调用它:请注意,该函数需要在FX应用程序线程上调用。一种方法是将呼叫打包在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); 
    } 
} 

(可能有比这更简单的方法:我不是在网页视图的Javascript <的专家 - > Java的通信,但是这似乎挺合我意。)