1

我有个问题。我在同一个 javafx 包中有两个类。一个带有 javascript 在 head 部分的单个 html 文件,一个 java 类(扩展应用程序)。现在的问题是,当我在 javafx webview 中显示页面后尝试单击按钮时,webView 中没有任何更新。下面是这两个文件的代码。请我需要知道为什么它不起作用。我从8小时以来一直在调试这个问题,没有成功。提前致谢。java类

    import java.net.MalformedURLException;
import java.net.URISyntaxException;
import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;

public class JavaFXApplication25 extends Application {
// inner class
public class Adder
{
    public double add(double n, double m)
    {
        return n + m;
    }
}

@Override
public void start(Stage primaryStage) throws URISyntaxException, MalformedURLException {
    WebView w = new WebView();
    WebEngine e = w.getEngine();
    e.setJavaScriptEnabled(true);
    e.load(this.getClass().getResource("tester.html").toURI().toURL().toExternalForm());
    Scene scene = new Scene(new VBox(w));
    primaryStage.setScene(scene);
    primaryStage.show();
   
    // make javascript aware of java object
    e.getLoadWorker().stateProperty().addListener(
    (p, o, n) ->{
        if(n == Worker.State.SUCCEEDED){
           JSObject b = (JSObject) e.executeScript("window");
            b.setMember("adder", new Adder());
        }
    }
    );
    
    
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

}

html文件

<html>
<head>
    <title>TODO supply a title</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script type="text/javascript">
        function addNum(){
            
        var n1 = Number(document.getElementById('num1').value);
        var n2 = Number(document.getElementById('num2').value);
        var n3 = adder.add(n1, n2); 
        document.getElementById('r').innerHTML = n3;
        }
    </script>
</head>
<body>
    <input type="text" id="num1" />
    <input type="text" id="num2" />
    <p> <span id="r"> </span></p>
    <button onclick="addNum()" >Add</button>
</body>

关键是程序运行并显示页面,但是在按下按钮时,页面上没有任何更新 我什至尝试在加载 html 页面之前进行调用,但是没有成功。请有人帮助检查代码中的错误。再次感谢。

现在下面是运行后的输出。即使多次单击“添加”按钮,它也不会显示任何内容!标准控制台上没有错误消息,什么都没有! 输出

4

2 回答 2

0
if(n == Worker.State.SUCCEEDED){
    JSObject b = (JSObject) e.executeScript("window");
    b.setMember("adder", new Adder());
}

欢迎来到 JavaFX 和 DOM 内容之间的 DOM 事件同步带来的痛苦。

工作状态“SUCCEEDED”并不一定意味着页面中加载了 DOM。

DOM 是在 document.onLoad() 处加载的……即使如此,它也是一种蠕虫罐头,因为到那时并非所有内容都已加载(图像和其他内容)。JQuery 有一个方便的JQuery(document).ready(function (e){ /*do whatever*/ })例程,您可以使用它来触发一些事情,让 JavaFX 知道它已准备好在 DOM 中做一些事情(基本上是您尝试使用上面的代码完成的事情[..]Worker.State.SUCCEEDED[..]

本质上,事件的顺序类似于:

1. JavaFX => Worker.state reaches SUCCEEDED STATE
2. DOM ====> Starts converting HTML into DOM components
3. ??? ====> This step is a complete mystery unbeknownst to even the savvy-est of skript kiddies. but i'm pretty sure this is where zuckerberg gets access to your webcam for a few frames. ... so beware!
4. DOM ====> Finishes doing its thing and fires off the onLoad() event which triggers the document.load() listener and associated function.
5. DOM ====> Officially inovkes the first JS function it comes across (not always the one you'd think it'd come across because JS is a magic programming language that doesn't give a shit about threads, or sequencing thereof, and anything goes when it comes JOs)
6. DOM+JS => Continues loading for some reason (i am not kidding)
7. DOM+JS => Some other weird flibbetlygibbletly bullshit done by the DOM and whatever javascript runs inside it ... if you're using timers... good luck.
8. DOM+JS => at this point, jQuery (if used) intercepts the .ready() event listener.
9. DOM+JS => believe me... stuff still isn't completely loaded. (because rampant JS scripts can add DOM components as they see fit and no .ready or .load event listener will ever be called.)

雪上加霜的是,这一系列事件可能需要 1 毫秒到 1 分钟之间的任何时间才能达到 (8)……这简直是任意的。

我结束了编写代码,开始比较节点树的变化,以确定何时开始弄乱 DOM ......但我离题了。

您需要确保在 DOM 准备好运行您的自定义 javascript 后启动您的 JS-JavaFX 通信协议。

把那个狗屎document.onLoad()放进去,在 JavaFX 中听它,然后像你已经这样做的那样设置加法器......然后希望最好。

于 2021-02-10T06:01:49.817 回答
0

谢谢大家...经过一些研究,我能够想出一个非常简单的解决方案..这里分步进行:

  1. 在主类中声明一个私有字段(它是包含要从 javascript 调用的公共方法的类的对象)。

  2. 实例化私有字段

  3. 加载后将成员添加到 Web 引擎

  4. 从javascript调用java方法。所以这里是更新的代码

         import java.net.MalformedURLException;
    

    导入 java.net.URISyntaxException;导入 javafx.application.Application;导入 javafx.concurrent.Worker;导入javafx.scene.Scene;导入javafx.scene.layout.VBox;导入javafx.scene.web.WebEngine;导入 javafx.scene.web.WebView;导入javafx.stage.Stage;导入 netscape.javascript.JSObject;

    public class JavaFXApplication25 extends Application { // 内部类 public class Adder { public double add(double n, double m) { return n + m; } }

    // STEP 1: 现在声明私有字段 (COMPULSORY)
    private Adder adder;

    @Override public void start(Stage primaryStage) 抛出 URISyntaxException, MalformedURLException { WebView w = new WebView(); WebEngine e = w.getEngine(); e.setJavaScriptEnabled(true); e.load(this.getClass().getResource("tester.html").toURI().toURL().toExternalForm()); 场景场景 = 新场景(新 VBox(w));primaryStage.setScene(场景); 主舞台.show();

    //STEP 2: 从 step1 实例化私有 js 对象 adder = new Adder(); // 让 javascript 知道 java 对象 e.getLoadWorker().stateProperty().addListener( (p, o, n) ->{ if(n == Worker.State.SUCCEEDED){ JSObject b = (JSObject) e. executeScript("window"); b.setMember("adder", new Adder()); } } );

    }

    /**

    • @param args 命令行参数 */ public static void main(String[] args) { launch(args); } }

HTML 代码仍然和以前一样。

//现在,我认为使用 jdk 8 及更高版本的 javafx 在这方面存在错误。我专门使用 jdk 8_126...版本。jvm似乎自动销毁了javascript处理程序类。幸运的是,将 js hanler 作为私有字段包装在主类中似乎可以防止这种可怕的发生。

于 2021-02-19T03:20:57.540 回答