javaFX webview window.onload is fired before loadworker succeeds

送分小仙女□ 提交于 2020-01-21 22:37:53

问题


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));
        }
    }
});

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>

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?

Any idea when I need to set mymember to have it ready when window.onload is executed?

Thanks!


回答1:


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.

So I've done this test:

    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);
    }

}

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

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.

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.




回答2:


Woks for all (including subsequent) pages: Where "java" is set in JAVA code:

window.setMember("java", new JavaApplication());

HTML (subsequent) page, keep waiting for 100ms if var "java" is not set (externally by JAVA):

 <script>                   
        function init(){
            if (typeof java !== 'undefined') {
                java.doSomething();
            }else{
                setTimeout(function(){ init() }, 100 );
            }
        }

        $(document).ready(function(){           
            init();         
        });
    </script> 


来源:https://stackoverflow.com/questions/25404817/javafx-webview-window-onload-is-fired-before-loadworker-succeeds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!