【问题标题】:Why doesn't the JavaScript method execute when inserted into the DOM from JavaFX?为什么从 JavaFX 插入 DOM 时 JavaScript 方法不执行?
【发布时间】:2015-11-21 04:57:39
【问题描述】:

我有一个大量使用 WebView 的 JavaFX 应用程序。我正在尝试将一个对象插入到 JavaScript 代码可以使用的 DOM 中,并且我需要这些对象在加载新页面时可用。

但是,当我运行程序时,FirebugLite 显示 DOM 中的对象,但函数不执行。

根据some Oracle documentation,这似乎是提供从 JavaScript 到 Java 的向上调用的适当方式。我还看到一些StackOverflow posts 解释了同样的事情。

我错过了什么?我在 Windows 7 上使用 Java 8、Update 51、64 位。

Java:

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>

萤火虫截图:

【问题讨论】:

    标签: javascript java javafx-8 javafx-webengine


    【解决方案1】:

    我相信正在发生的事情是 WebEngine 加载页面,ChangeListener 在各个点被调用(SCHEDULED、RUNNING、SUCCEEDED 等)。一旦 Worker.State.SUCCEEDED 事件发生,页面就已经完成了所有内容的加载,并且也完成了该内容的执行。所以基本上我在 JavaScript 代码中对 Debug.print() 的调用很早就发生了,并且调用了一个 undefinednull 的对象。

    无论如何,这是我最好的猜测,因为如果我在添加对象之后添加一个由 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() .

    【讨论】:

      猜你喜欢
      • 2016-10-24
      • 2021-05-09
      • 1970-01-01
      • 1970-01-01
      • 2019-12-23
      • 2011-12-17
      • 2015-12-02
      • 2014-03-11
      • 2019-09-30
      相关资源
      最近更新 更多