从 JavaFX Web 视图调用 Java 方法

Calling a Java method from a JavaFX webview

本文关键字:Java 方法 调用 视图 JavaFX Web      更新时间:2023-09-26

在我的项目中,我有一个显示在JavaFx WebView中的HTML文档。我有一个Javascript函数,它应该调用Java方法getData(目前它只打印传递的变量,以便我可以确认数据正在从WebView传递回Java应用程序):

    public void getData(String s){
        System.out.println(s);
    }

这就是我尝试将调用 Java 方法的功能添加到我的 WebView 网页中的方式:

    JSObject win = (JSObject) webEngine.getDocument();
    win.setMember("app", new Bridge());

这是我用来调用getData的JavaScript函数:

     function interOp(val){
        app.getData(val);
     }

此函数在 <select> 标记上的 onchange 事件上调用。我遵循的指南似乎正是这样做的,但是当我运行程序时,控制台上不会打印任何内容。

我找到了这个问题的解决方案:不要使用 webEngine.getDocument(); ,它返回一个HTMLdocument对象,而是使用 webEngine.executeScript("window"); 它提供了一个窗口对象。

我的解决方案是在传递对象之前创建对象...所以这个:

JSObject win = (JSObject) webEngine.getDocument();
win.setMember("app", new Bridge());"

变成这样:

Bridge bridgeREF = new Bridge();
JSObject win = (JSObject) webEngine.getDocument();
win.setMember("app", bridgeREF);

这来自我在这里读到的错误报告:https://bugs.openjdk.java.net/browse/JDK-8170515

否则,javascript 调用似乎有一半的时间有效......有时需要刷新。 这真的很奇怪。

虽然我的代码有点不同...以下是我如何使用JavaFX窗口注册Java类"JavaApp":

        Platform.runLater(new Runnable() {
        @Override
        public void run() {
  JavaApp appREF = new JavaApp(webEngine); 
  webEngine.getLoadWorker().stateProperty().addListener(
        new ChangeListener<State>() {
          @Override public void changed(ObservableValue ov, State oldState, State newState) {
              if (newState == Worker.State.SUCCEEDED) {
                  JSObject win = (JSObject) webEngine.executeScript("window");
                    win.setMember("app", appREF);  
            }
            }
        });
   //other code for loading html, listeners, etc...
   }

对类的引用应在匿名侦听器之外创建,否则垃圾回收器可能会获取它。 这就是(我认为)导致我所经历的不稳定行为的原因...... 您的Java类可能需要也可能不需要对webEngine的引用。我用它来在发送文件后加载另一个 url。

我认为无论您使用窗口还是文档都无关紧要...除了该窗口可能更持久,具体取决于您是否使用整页加载。

我认为这取决于您如何从网页调用 Java 方法,我指出了事件。我认为不支持onchangeonfocus事件,仅支持与鼠标相关的事件。但我对此不太确定。

关于JSObject类,webEngine.executeScript("window");应该可以工作。

你可以从我的问题中看到一个完整的工作示例 这里.

希望它对你有帮助。

我看到如果我使用方法

JSObject win = (JSObject) webEngine.getDocument();
win.setMember("app", new Bridge());"

这是工作,但如果我调整窗口大小,则不会捕获事件。

我还需要使用

-javaagent:javaagent-shaded.jar

在我的运行命令(我从 Eclipse 命令复制它)中使用 Java 11:

java '
-javaagent:javaagent-shaded.jar '
-Dfile.encoding=UTF-8 '
-p /home/odroid/Scaricati/TestFX/bin:'
/usr/share/java/javafx-base.jar:'
/usr/share/java/javafx-controls.jar:'
/usr/share/java/javafx-fxml.jar:'
/usr/share/java/javafx-graphics.jar:'
/usr/share/java/javafx-media.jar:'
/usr/share/java/javafx-swing.jar:'
/usr/share/java/javafx-swt.jar:'
/usr/share/java/javafx-web.jar '
-m TestFX/application.Main