JavaFX窗口上的一致setMember

时间:2016-03-02 21:21:02

标签: java javafx webview javafx-8

我正在尝试在基于JavaFX的UI中使用webview。每当某些操作发生时,必须通过调用.load(...)方法来更改webview的内容。每次加载后,我必须在webview中的窗口对象上设置一些不同的值。然后将这些值用在JavaScript代码中,该代码使用jQuery在文档的ready事件上运行:

$(document).ready(function() { 
    // here I use values set on window to populate/manipulate HTML elements
});

我正在按照Oracle的指南获取窗口对象,并在其上使用setMember来传递我需要的值here。但是,当第一次调用webView.load时,与之后调用时相比,我遇到了不一致的问题。问题是,第一次可以在加载内容之前在窗口对象上设置值。这意味着JavaScript将拥有所需的数据。然而,在随后的调用中,我找不到在正确的时刻设置值的方法。这些值要么在旧窗口对象上设置得太早,要么在文档更改后删除,或者设置得太晚, JavaScript完成运行后

我尝试在webView.getEngine().getLoadWorker().stateProperty().addListener(...)webEngine.documentProperty().addListener(...)设置值,前者太早,后者太晚。

我找到了一个解决方案,在webEngine.documentProperty().addListener(...)上调用显式JavaScript函数。但这阻止了我在Web和Java项目之间共享相同的UI。重要的是找到一种方法来解决这个(我想说的)错误并具有适当的一致功能。

我知道之前已经提出了类似的问题,但对于非这些问题,与网络上的行为完全相同并不重要。

更新 添加一个小例子来进一步澄清问题:

public class WebEngineLoadBug extends Application {

    private WebEngine webEngine;
    private WebView webView;

    /**
     * @param args ignored.
     */
    public static void main(final String[] args) {
        launch(args);
    }

    @Override
    public void start(final Stage primaryStage) throws Exception {
        webView = new WebView();
        webEngine = webView.getEngine();

        // alert is the safest way to pass on data
        webEngine.setOnAlert(new EventHandler<WebEvent<String>>() {
            @Override
            public void handle(WebEvent<String> event) {
                System.out.println(event.getData());
            }
        });

        primaryStage.setScene(new Scene(webView));
        primaryStage.show();

        load1();
    }

    public void load2() {
        System.out.println("loading 2 ...");

        // second load
        JSObject dom2Window = (JSObject) webEngine.executeScript("window");
        dom2Window.setMember("variable2Name", "variable value 2");
        dom2Window.setMember("ctr", this);

        // this load does NOT work as expected, variable2Name is NOT set before JavaScript runs and it can NOT be accessed in document ready event
        webEngine.load(WebEngineLoadBug.class.getResource("/file2.html").toExternalForm());
    }

    public void load1() {
        System.out.println("loading 1 ...");

        // first load
        JSObject domWindow = (JSObject) webEngine.executeScript("window");
        domWindow.setMember("variableName", "variable value 1");
        domWindow.setMember("ctr", this);

        // this load works perfectly, variableName is set before JavaScript runs and it can be accessed in document ready event
        webEngine.load(WebEngineLoadBug.class.getResource("/file1.html").toExternalForm());
    }


}

这是file1.html

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-2.2.1.min.js"></script>
</head>
<body>
<h1 id="title">FILE 1</h1>

<a href="#" onclick="event.preventDefault(); ctr.load2();">load 2</a>

<script>
    alert('file1');

    $(document).ready(function () {
        // use variableName here
        $("#title").html(variableName);

        alert(variableName);
    });
</script>

</body>
</html>

file2.html

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-2.2.1.min.js"></script>
</head>
<body>
<h1 id="title">FILE 2</h1>

<a href="#" onclick="event.preventDefault(); ctr.load1();">load 1</a>

<script>
    alert('file2');

    $(document).ready(function () {
        // use variableName here
        $("#title").html(variable2Name);

        alert(variable2Name);
    });
</script>

</body>
</html>

问题在控制台上可见,您将看到这些行:

loading 1 ...
file1
variable value 1
loading 2 ...
file2

问题是此处缺少variable value 2,并且未加载第二页的标题。即使您向前和向后导航到页面,您也会看到值不再正确传递。

0 个答案:

没有答案