在loadworker成功之前触发javaFX webview window.onload [英] javaFX webview window.onload is fired before loadworker succeeds
问题描述
我在我的应用程序中使用JavaFX webview。使用以下代码,我在页面加载后设置了一个成员
I use a JavaFX webview in my application. With the following code I set a member after the page has been loaded
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("mymember", new JavaScriptBridge(this));
}
}
});
现在在javascript中我可以调用 mymember.doSomething()
例如当我按下按钮并且它已成功执行时调用,但如果我将以下代码添加到html
Now in javascript I can invoke mymember.doSomething()
e.g. called when I press the button and it's executed successfully, but if I add the following code to the html
<script>
function startup() {
mymember.doSomething();
}
window.onload=startup;
</script>
加载页面时不会自动执行。似乎 window.onload
在 LoadWorker
收到通知之前执行。所以 mymember
尚未设置。但另一方面,在加载html之前,我无法设置 mymember
,对吗?
It's not executed automatically when the page is loaded. It seems like window.onload
is executed before the LoadWorker
gets notified. So mymember
is not set yet. But on the other hand, I cannot set mymember
before the html has been loaded, right?
任何想法何时我需要设置 mymember
以便在 window.onload
执行时准备好吗?
Any idea when I need to set mymember
to have it ready when window.onload
is executed?
谢谢!
推荐答案
对于这个问题的答案可能为时已晚,但在回答这个问题,我一直试图找到 executeScript
。
Maybe it's too late for an answer to this problem, but after answering this question, I've been trying to find a reason why executeScript
has to be called after the complete load of the webpage.
所以我做了这个测试:
public class EarlyWebEngineTest extends Application {
@Override
public void start(Stage stage) {
final WebView webView = new WebView();
final WebEngine webEngine = webView.getEngine();
// Early call of executeScript to get a JavaScript object, a proxy for the
// Java object to be accessed on the JavaScript environment
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("app", new JavaApplication());
webEngine.getLoadWorker().stateProperty().addListener((ov,oldState,newState)->{
if(newState==State.SCHEDULED){
System.out.println("state: scheduled");
} else if(newState==State.RUNNING){
System.out.println("state: running");
} else if(newState==State.SUCCEEDED){
System.out.println("state: succeeded");
}
});
Button button=new Button("Load Content");
button.setOnAction(e->webEngine.loadContent("<html>"
+ " <script>function initialize() {"
+ " var nameVar = \"This is a JS var\"; "
+ " app.callJavascript(nameVar);"
+ "} </script>"
+ " <body onLoad=\"initialize()\">Hi, this is a test!</body>"
+ "</html>"));
VBox vbox = new VBox(10,button,webView);
Scene scene = new Scene(vbox,400,300);
stage.setScene(scene);
stage.show();
}
public class JavaApplication {
public void callJavascript(String msg){
System.out.println("JS>> "+msg);
}
}
public static void main(String[] args) {
launch(args);
}
}
直到单击按钮,但我们已经在浏览器上创建了JavaScript对象。
The content is not loaded until the button is clicked, but we've already created the JavaScript object on the browser.
在单击按钮之前,输出控制台上没有任何内容。但是如果我们点击按钮......这就是输出:
Before clicking the button, there's nothing on the output console. But if we click the button... this is the output:
state: scheduled
state: running
JS>> This is a JS var
state: succeeded
正如我们所看到的,Java对象是在执行后者之前有效地传递给脚本,并且在加载内容时成功调用 app.callJavascript
。
As we can see, the Java object is effectively passed to the script before the latter is executed, and app.callJavascript
is successfully called while the content is being loaded.
请注意,出于访问加载的DOM的常见目的,在 State.SUCCEEDED
executeScript 的常用方法>仍然是推荐的方式。
Note that for the common purpose of accessing the loaded DOM, the usual approach of calling executeScript
after State.SUCCEEDED
is still the recommended way.
这篇关于在loadworker成功之前触发javaFX webview window.onload的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!