问题
The following code works on Linux, but the callback does not work on Windows (VirtualBox VM). Can you please tell me why?
Java:
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>
回答1:
The trick was to create the Callback as a class field:
private Callback callback = new Callback ();
And then:
webEngine.load (getClass ().getResource ("WebViewTest.html").toString ());
JSObject window = (JSObject) webView.getEngine ().executeScript ("window");
// BUG // window.setMember ("java", new Callback ());
window.setMember ("java", callback);
Maybe there is some abusive garbage collecting on Windows? I don't know...
回答2:
The window
object is likely replaced when a new DOM is loaded into the web engine. Try setting the callback when the document is loaded:
Callback callback = new Callback();
webEngine.documentProperty().addListener((obs, oldDoc, newDoc) -> {
if (newDoc != null) {
JSObject window = (JSObject) webView.getEngine ().executeScript ("window");
window.setMember ("java", callback);
}
});
(You can see that the window
object changes by System.out.println(System.identityHashCode(webView.getEngine ().executeScript ("window"))
before loading the HTML, and System.out.println(System.identityHashCode(window))
in the document listener.)
回答3:
I had a similar problem and after digging deep, I found out that you are supposed to call window.setMember ("java", new Callback ());
after rendering your html so this should work:
JSObject window = (JSObject) webView.getEngine ().executeScript ("window");
webEngine.load (getClass ().getResource ("WebViewTest.html").toString ())
window.setMember ("java", new Callback ());
Also note that if you perform a reload or if you navigate to another page, you will lose your functionality again. A solid solution will be:
webEngine.documentProperty().addListener(((observable, oldValue, newValue) -> {
if (Objects.nonNull(newValue)) {
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("engine", callback);
}
}));
来源:https://stackoverflow.com/questions/41537474/cannot-call-javafx-from-webview-javascript-on-windows-virtualbox