无法从Windows上的WebView JavaScript调用JavaFX(VirtualBox)

时间:2017-01-08 20:24:18

标签: javascript java javafx webview

以下代码适用于Linux,但回调在Windows(VirtualBox VM)上不起作用。你能告诉我为什么吗?

爪哇:

    public class WebViewTest extends Application {
      private Label label = new Label ("...");
      public static void main (String[] args) {
        launch (args);
      }
      @Override
      public void start (Stage stage) throws Exception {
        WebView webView = new WebView ();
        WebEngine webEngine = webView.getEngine ();
        webEngine.setJavaScriptEnabled (true);
        JSObject window = (JSObject) webView.getEngine ().executeScript ("window");
        window.setMember ("java", new Callback ());
        webEngine.load (getClass ().getResource ("WebViewTest.html").toString ());
        BorderPane pane = new BorderPane ();
        pane.setCenter (webView);
        pane.setBottom (label);
        Scene scene = new Scene (pane);
        stage.setScene (scene);
        stage.show ();
      }
      public class Callback {
        public void click () {
        label.setText ("Clicked :-)");
      }
    }
  }

HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>Test</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <button onclick="window.java.click ();">Test</button>
  </body>
</html>

3 个答案:

答案 0 :(得分:4)

诀窍是将Callback创建为类字段:

private Callback callback = new Callback ();

然后:

webEngine.load (getClass ().getResource ("WebViewTest.html").toString ());
JSObject window = (JSObject) webView.getEngine ().executeScript ("window");
// BUG // window.setMember ("java", new Callback ());
window.setMember ("java", callback);

也许在Windows上有一些垃圾收集?我不知道......

答案 1 :(得分:0)

当新的DOM加载到Web引擎中时,window对象可能会被替换。尝试在加载文档时设置回调:

Callback callback = new Callback();
webEngine.documentProperty().addListener((obs, oldDoc, newDoc) -> {
    if (newDoc != null) {
        JSObject window = (JSObject) webView.getEngine ().executeScript ("window");
        window.setMember ("java", callback);                
    }
});

(您可以看到window对象在加载HTML之前按System.out.println(System.identityHashCode(webView.getEngine ().executeScript ("window"))更改,并在文档侦听器中更改System.out.println(System.identityHashCode(window))。)

答案 2 :(得分:0)

我遇到了类似的问题,在深入研究之后,我发现您应该在渲染html后调用window.setMember ("java", new Callback ());,这样就可以了:

JSObject window = (JSObject) webView.getEngine ().executeScript ("window");
webEngine.load (getClass ().getResource ("WebViewTest.html").toString ())
window.setMember ("java", new Callback ());

还请注意,如果执行重新加载或导航到另一页,则会再次失去功能。一个可靠的解决方案是:

webEngine.documentProperty().addListener(((observable, oldValue, newValue) -> {
   if (Objects.nonNull(newValue)) {
        JSObject window = (JSObject) webEngine.executeScript("window");
        window.setMember("engine", callback);
    }
}));