如何在加载页面后在JavaFx.WebView中运行javascript代码?

时间:2014-06-20 14:35:52

标签: java javascript javafx

我使用了这段代码

public WebMap() {
    webView = new WebView();
    final WebEngine webEngine = webView.getEngine();
    String url = getClass().getResource("map.html").toExternalForm();
    webEngine.load(url);

    final Deferred d = new Deferred();
    webEngine.getLoadWorker().stateProperty().addListener(
        new ChangeListener<State>() {
            @Override
            public void changed(ObservableValue ov, State oldState, State newState) {
                if (newState == State.SUCCEEDED) {
                    d.resolve(webEngine);
                }
            }
        }
    );
    readyWebEngine = d.promise();
}

我没有直接调用webEngine.executeScript,但我使用

readyWebEngine.then(new PromiseFunc() {
            @Override
    public Promise apply(Object oWebEngine) {
        WebEngine webEngine = (WebEngine)oWebEngine;
        webEngine.executeScript(script); // <=============================
                // return value doesn't matter
        return (new Deferred()).promise();
    }
});

这样,script字符串不会被评估,直到通过调用d.resolve()来解决(履行)承诺

我们假设promise库是正确的

该代码对我来说效果很好,但是我的一位同事得到了这个令人沮丧的错误

netscape.javascript.JSException: ReferenceError: Can't find variable: gotoLatLng
[com.sun.webpane.platform.WebPage.twkExecuteScript(Native Method), com.sun.webpane.platform.WebPage.executeScript(WebPage.java:1438), javafx.scene.web.WebEngine.executeScript(WebEngine.java:811), packagename.WebMap.WebMap$1.apply(WebMap.java:36), packagename.WebMap.promise.Deferred$1$1.apply(Deferred.java:23), packagename.WebMap.promise.Deferred.resolve(Deferred.java:40), packagename.WebMap.WebMap$2.changed(WebMap.java:57), packagename.WebMap.WebMap$2.changed(WebMap.java:52), com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196), com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100), javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:195), javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:161), javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:130), javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:163), javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:975), javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1086), javafx.scene.web.WebEngine$LoadWorker.access$600(WebEngine.java:968), javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:955), com.sun.webpane.platform.WebPage.fireLoadEvent(WebPage.java:2356), com.sun.webpane.platform.WebPage.fwkFireLoadEvent(WebPage.java:2204), com.sun.webpane.webkit.network.URLLoader.twkDidFinishLoading(Native Method), com.sun.webpane.webkit.network.URLLoader.access$1300(URLLoader.java:44), com.sun.webpane.webkit.network.URLLoader$6.run(URLLoader.java:691), com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76), com.sun.glass.ui.win.WinApplication._runLoop(Native Method), com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:17), com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:67), java.lang.Thread.run(Thread.java:744)]

包含javascript代码的html页面经过了充分测试。我们假设那里没有javascript错误

错误netscape.javascript.JSException: ReferenceError: Can't find variable: gotoLatLng并不会发生在我身上,因为在loadWorker的newState == State.SUCCEEDED之后执行了javascript代码。

问题在于,在我的同事程序的堆栈跟踪中,我们可以看到WebEngine.executeScript(WebEngine.java:811)被调用

packagename.WebMap.promise.Deferred.resolve(Deferred.java:40), packagename.WebMap.WebMap$2.changed(WebMap.java:57), packagename.WebMap.WebMap$2.changed(WebMap.java:52), com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196), com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100), 

因此,当load changed event时,newState == State.SUCCEEDED的监听器会调用executeScript,这意味着页面已完全加载并且加载了s中的javascript(应该定义变量)。

很抱歉,因为我无法访问我的同事代码,但它基于我的代码。现在我不确定这段代码是否在适当的时候执行javascript代码

webEngine.getLoadWorker().stateProperty().addListener(
        new ChangeListener<State>() {
            @Override
            public void changed(ObservableValue ov, State oldState, State newState) {
                if (newState == State.SUCCEEDED) {
                    webEngine.executeScript(script);
                }
            }
        }
    );

任何帮助?

1 个答案:

答案 0 :(得分:2)

怎么样

$(function(){
    alert("command:ready");
});

然后

engine.onAlert = new EventHandler<WebEvent<String>>() {
    @Override
    void handle(WebEvent<String> event) {
        if("command:ready".equals(event.getData())){
        //TODO: initialize
        }
    }
}

(见http://habrahabr.ru/company/codeorchestra/blog/198776/