【问题标题】:How to create a JavaScript wrapper to be used with JavaFx WebView? Is JSNI an option?如何创建与 JavaFx WebView 一起使用的 JavaScript 包装器? JSNI 是一种选择吗?
【发布时间】:2025-12-23 04:25:15
【问题描述】:

我想将 JavaFx WebEngine 与 JavaScript 库 d3.js 结合使用。我已经能够从 Java 中访问 JavaScript 库。这可以使用 JSObjects,如 [1] 所示:

JSObject d3Object = (JSObject) webEngine.executeScript("d3");
JSObject chart= (JSObject) d3Object.call("select", ".chart");

如您所见,有一个通用方法“调用”,我必须将要调用的 JavaScript 方法的名称作为字符串传递。为了更舒适地使用 JavaScript 库 d3.js,我想要一个 Java 包装器,例如

JSObject d3Object = (JSObject) webEngine.executeScript("d3");
D3Wrapper d3 = new D3Wrapper(d3Object);
Selection chart = d3.select(".chart");

创建这样一个 JavaScript 包装器的推荐方法是什么?我发现已经有一个针对 GWT 应用程序的 D3 包装器。 d3 对象的主要包装器位于此处:

https://github.com/gwtd3/gwt-d3/blob/master/gwt-d3-api/src/main/java/com/github/gwtd3/api/D3.java

它似乎是基于 JSNI [2] 并且示例方法定义是

public static final native Selection select(String selector)/*-{
    return $wnd.d3.select(selector);
}-*/;

从 Java 中调用方法时,将执行注释中的本机代码。如何在我的 JavaFx 桌面应用程序中利用现有的包装器代码?我以前从未使用过 GWT,也不想运行额外的 Web 服务器。我真的需要深入研究 GWT 并在 JavaFx WebEngine 中运行完整的 GWT 应用程序(如果可能的话)?或者我可以以某种方式仅将 GWT 的 JSNI 部分与 JavaFx WebEngine 一起使用吗?

这是一篇关于 GWT 调试模式的文章,看起来很复杂:http://www.quora.com/How-does-GWT-live-javascript-debugging-in-Eclipse-work-and-how-could-it-be-applied-to-Clojure 所以恐怕没有简单的方法可以将 WebEngine 插入到这样的工作流程中?我真的需要手动重写“gwt-d3 已经提供”的每个包装类吗?如果本机 JavaScript 代码由 Annotations 给出,我可以重用 gwt-d3 中的包装类并通过反射处理它们。

如果将 JSNI 与 JavaFx 结合起来没有任何意义,那么为 d3.js 编写自己的包装器的优雅方法是什么?是否有 Java 库可以帮助我编写 JavaScript 包装器?

【问题讨论】:

    标签: javascript d3.js javafx wrapper jsni


    【解决方案1】:

    事实证明,JSNI 不是(可行的)选项。我决定从 gwt-d3 中现有的包装器代码开始,并通过搜索和替换操作对其进行转换......并进行一些手动微调。这样它就不再适用于 GWT,但适用于 JavaFx。我将为转换后的代码创建一个新的 GitHub 项目。

    我的包装类继承自一个抽象基类 JavaScriptObject,它与 JavaFx WebEngine 对话并处理 JSObject 操作。与gwt-d3作者的相关讨论可以在这里找到:https://github.com/gwtd3/gwt-d3/issues/124

    编辑

    我刚刚创建了一个新的 GitHub 项目:

    https://github.com/stefaneidelloth/javafx-d3

    请随时加入并帮助修复剩余的错误。

    【讨论】:

      最近更新 更多