JavaFX教程 – JavaFX WebEngine
JavaFX 提供与 HTML5 内容互操作的功能。
JavaFX 中的底层网页渲染引擎是名为 WebKit 的流行的开源API。此 API 用于 Apple 的 Safari 浏览器,Amazon 的 Kindle 设备,并在 Google 的 Chrome 浏览器中使用。
嵌入式浏览器使您能够在 JavaFX 应用程序中执行以下任务:
- 从本地或远程
URL
呈现 HTML - 获取网络历史记录
- 执行
JavaScript
命令 - 从
JavaScript
调用 JavaFX
- 管理网络弹出窗口
WebEngine
JavaFX 提供了一个能够加载 HTML5 内容的非 GUI 组件,称为 WebEngine API
(javafx.scene.web.WebEngine
)。
这个 API 基本上是一个 WebEngine
类的对象实例,用于加载包含 HTML5 内容的文件。
要加载的 HTML5 文件可以位于本地文件系统,Web 服务器或 JAR 文件中。
使用 Web 引擎对象加载文件时,将使用后台线程来加载 Web 内容,以便它不会阻止 JavaFX 应用程序线程。
从网址载入
我们可以通过使用 WebEngine
的load()
方法从 URL
加载 Web 内容。
WebEngine
使用后台线程,坚持基于事件的编程模型。
Web 引擎可以从远程 Web 服务器异步加载 Web 内容,并在内容加载完成时通知处理程序代码。
以下代码从后台工作线程中的远程 Web 服务器加载 HTML 内容。
要监视或确定工作线程是否已完成 javafx.beans.value.ChangeListener
添加到 state
属性。
import javafx.application.Application; import javafx.concurrent.Worker.State; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.web.WebEngine; import javafx.stage.Stage; public class Main extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { WebEngine webEngine = new WebEngine(); webEngine.getLoadWorker().stateProperty() .addListener((obs, oldValue, newValue) -> { if (newValue == State.SUCCEEDED) { System.out.println("finished loading"); } }); // addListener() // begin loading... webEngine.load("http://www.www.w3cschool.cn"); Group root = new Group(); Scene scene = new Scene(root, 300, 250); primaryStage.setScene(scene); primaryStage.show(); } }
以下是所有可能的工作线程状态:
- READY
- SCHEDULED
- RUNNING
- SUCCEEDED
- CANCELLED
- FAILED
加载HTML字符串
我们可以使用WebEngine
的loadContent()
方法将 HTML 字符串加载到WebEngine
。
Web 引擎的 loadContent
(String htmlText
) 方法可以加载表示为字符串的 HTML 内容动态而不必从远程服务器获取内容。
以下代码段加载预先生成的 HTML 内容:
webEngine.loadContent("<html><body><b>JavaFX</b></body></html>");
HTML DOM内容
Web 引擎能够按照基于 W3C 标准的 Java API 来将当前页面的文档对象模型(DOM)加载为 XML 内容。
在 Web 引擎实例成功加载 HTML 内容后,可以通过调用Web引擎的 getDocument()
方法轻松获取 XML DOM。
以下代码获取一个 Document
(org.w3c.dom.Document
) 实例,假设 Web 引擎完成加载 HTML 或 XML 内容。
import javafx.application.Application; import javafx.concurrent.Worker.State; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.web.WebEngine; import javafx.stage.Stage; public class Main extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { WebEngine webEngine = new WebEngine(); webEngine.getLoadWorker().stateProperty() .addListener((obs, oldValue, newValue) -> { if (newValue == State.SUCCEEDED) { System.out.println("finished loading"); org.w3c.dom.Document xmlDom = webEngine.getDocument(); System.out.println(xmlDom); } }); // addListener() // begin loading... webEngine.load("http://www.www.w3cschool.cn"); Group root = new Group(); Scene scene = new Scene(root, 300, 250); primaryStage.setScene(scene); primaryStage.show(); } }
以文本字符串的形式获取原始XML数据
以下代码将 XML DOM 转换为String
。
import java.io.StringWriter; import javafx.application.Application; import javafx.concurrent.Worker.State; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.web.WebEngine; import javafx.stage.Stage; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; public class Main extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { WebEngine webEngine = new WebEngine(); webEngine .getLoadWorker() .stateProperty() .addListener( (obs, oldValue, newValue) -> { System.out.println(newValue); if (newValue == State.SUCCEEDED) { System.out.println("finished loading"); try { TransformerFactory transformerFactory = TransformerFactory .newInstance(); Transformer transformer = transformerFactory.newTransformer(); StringWriter stringWriter = new StringWriter(); transformer.transform(new DOMSource(webEngine.getDocument()), new StreamResult(stringWriter)); String xml = stringWriter.getBuffer().toString(); System.out.println(xml); } catch (Exception e) { e.printStackTrace(); } } }); // addListener() // begin loading... webEngine.load("http://www.www.w3cschool.cn"); Group root = new Group(); Scene scene = new Scene(root, 300, 250); primaryStage.setScene(scene); primaryStage.show(); } }
通过 JavaScript 桥接生成 HTML5 内容
JavaFX 的 WebEngine AP I有一个 JavaScript 桥梁,允许 Java 代码调用 HTML5 内容中的 JavaScript 函数或脚本代码。
要获取原始 HTML5,您需要与 JavaScript 桥接器交互,以使用 Web 引擎的 executeScript()
方法访问 Web 内容的 DOM。
以下代码访问HTML文档(DOM)以从 documentElement.outerHTML
获取原始内容:
String html = (String) webEngine.executeScript("document.documentElement.outerHTML");
import javafx.application.Application; import javafx.concurrent.Worker.State; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.web.WebEngine; import javafx.stage.Stage; public class Main extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { WebEngine webEngine = new WebEngine(); webEngine .getLoadWorker() .stateProperty() .addListener( (obs, oldValue, newValue) -> { System.out.println(newValue); if (newValue == State.SUCCEEDED) { System.out.println("finished loading"); String html = (String) webEngine .executeScript("document.documentElement.outerHTML"); System.out.println(html); } }); webEngine.load("http://www.www.w3cschool.cn"); Group root = new Group(); Scene scene = new Scene(root, 300, 250); primaryStage.setScene(scene); primaryStage.show(); } }
从 Java 传递到 JavaScript
以下代码显示了如何从 Java 代码调用 JavaScript
函数。
假设我们有一个具有以下 JavaScript
函数的网页
... <script> function sayHello( msg ) { document.getElementById("my_message").innerHTML = msg; } </script> <div id="my_message"></div>
我们可以从 Java 代码调用该函数 webEngine.executeScript(“sayHello("Hi there“);");
从 JavaScript 传递到 Java
JavaFX 允许 JavaScript
代码调用 Java 代码。
import javafx.application.Application; import javafx.concurrent.Worker; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.web.WebEngine; import javafx.stage.Stage; import jdk.nashorn.api.scripting.JSObject; public class Main extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { WebEngine webEngine = new WebEngine(); webEngine.getLoadWorker().stateProperty() .addListener((obs, oldValue, newValue) -> { if (newValue == Worker.State.SUCCEEDED) { JSObject jsobj = (JSObject) webEngine.executeScript("window"); jsobj.setMember("ABCD", new HelloWorld()); } }); webEngine.load("http://www.www.w3cschool.cn"); Group root = new Group(); Scene scene = new Scene(root, 300, 250); primaryStage.setScene(scene); primaryStage.show(); } } class HelloWorld { public String sayGoodbye(String name) { return "hi:" + name; } }
JavaScript
代码调用 Java 代码
<script> function sayGoodbye(name) { var message = ABCD.sayGoodbye(name); document.getElementById("my_message").innerHTML = message; } </script> <div id="my_message"></div>