我有一个大量使用WebView的JavaFX应用程序。我试图将一个对象插入到JavaScript代码可以使用的DOM中,并且我需要在加载新页面时使用这些对象。
但是,当我运行程序时,FirebugLite会在DOM中显示对象,但函数不会执行。
根据some Oracle documentation,这似乎是提供从JavaScript到Java的upcalls的适当方式。我也看到一些StackOverflow posts解释同样的事情。
我错过了什么?我在Windows 7上使用Java 8,Update 51,64位。
爪哇:
public class DemoApplication extends Application {
Debug debug;
@Override
public void start(final Stage stage) throws Exception {
debug = new Debug();
WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
if (newValue == Worker.State.SUCCEEDED) {
JSObject windowObject = (JSObject) webEngine.executeScript("window");
windowObject.setMember("Debug", debug);
}
}
}
);
webEngine.load("http://localhost:8080/page1.html");
stage.setScene(new Scene(browser));
stage.show();
}
}
public class Debug {
public void print(final Object text) {
System.err.println(text);
}
}
HTML / JavaScript的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="https://getfirebug.com/firebug-lite.js"></script>
<script>
Debug.print("Hello");
</script>
</head>
<body>
Page 1
<a href="page2.html">Page 2</a>
</body>
</html>
Firebug屏幕截图:
答案 0 :(得分:3)
我相信正在发生的事情是WebEngine加载页面,ChangeListener在各个点调用(SCHEDULED,RUNNING,SUCCEEDED等)。一旦发生了Worker.State.SUCCEEDED事件,该页面已经完成了所有内容的加载,并且已经完成执行该内容。所以基本上我在JavaScript代码中对Debug.print()的调用很早就发生了,并调用了一个 undefined 或 null 的对象。
无论如何,这是我最好的猜测,因为如果我在添加对象后添加由Java部分执行的JavaScript函数,一切都按预期工作。
这就是我修改JavaScript方面的方法:
<script>
// callback that uses java objects
window.ready = function() {
Debug.print("Hello");
}
</script>
这就是我修改Java方面的方式:
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
if (newValue == Worker.State.SUCCEEDED) {
JSObject windowObject = (JSObject) webEngine.executeScript("window");
windowObject.setMember("Debug", debug); // insert object
windowObject.call("ready"); // execute callback
}
}
}
);
这里的关键更改是JavaScript中的ready()函数,并在注入Java端的对象之后调用该函数。这可确保在调用之前这些对象可用。
我在几个不同的页面上尝试了这个,当从一个页面到另一个页面时,当ready()函数被调用时,Debug.print()正确执行,即使使用WebEngine.reload()或WebHistory.go()