Руководство JavaFX WebView и WebEngine
View more Tutorials:
JavaFX WebView это минибраузер, так же называется встроенным браузером (embedded browser) в приложение JavaFX. Этот браузер основан на WebKit, браузерный движок (browser engine) с открытым исходным кодом, поддерживает CSS, JavaScript, DOM и HTML5.
JavaFX WebView позволяет вам выполнять следующие задачи в приложении JavaFX:
- Изображает содержание HTML от локальных и удаленных URL
- Собирает историю веб
- Выполняет команды Javascript
- Выполняет вызовы от Javascript до JavaFX
- Управляет поп ап окна в веб
- Применяет эффекты для встроенного браузера
В настоящей версии (JavaFX 2.3) компонент WebView поддерживает следующие свойства HTML5:
- Canvas
- Media Playback
- Form controls (except for <input type="color"> )
- Editable content
- History maintenance
- Support for the <meter> and <progress> tags.
- Support for the <details> and <summary> tags.
- DOM
- SVG
- Support for domain names written in national languages
Следующее изображение является структурой встренного браузера в JavaFX:

WebEngine
Класс WebEngine предоставляет основную функцию веб страницы. Он поддерживает в интерктивности пользователя, как навигация ссылок и submit form HTML, несмотря на то что он не интерактирует напрямую с пользователем. Класс WebEngine обрабатывает веб страницу одновременно. Он поддерживает основные веб ствойства загрузки содержания HTML и доступ в DOM так же выполняет команды JavaScript.
WebView
Класс WebView расширен из класса Node, он оборачивает объект WebEngine и отображает содержание Html. Вы можете получить объект WebEngine из WebView используя метод getEngine().
// Create a WebView WebView browser = new WebView(); // Get WebEngine via WebView WebEngine webEngine = browser.getEngine(); // Load page webEngine.load("http://eclipse.com");
Загрузить удаленный URL.
WebView browser = new WebView(); WebEngine webEngine = browser.getEngine(); String url = "https://eclipse.org"; // Load a page from remote url. webEngine.load(url);
Помимо отображения данных из удаленного URL, вы так же можете отобразить содержание статистического HTML.
// A HTML text String html = "<html><h1>Hello</h1><h2>Hello</h2></html>"; // Load content. webEngine.loadContent(html); // Or webEngine.loadContent(html,"text/html");
Или загрузить содержание html из локального файла.
File file = new File("C:/test/a.html"); URL url= file.toURI().toURL(); // file:/C:/test/a.html webEngine.load(url.toString());
Посмотрим полный пример с WebView. Заметьте, что WebView по умолчанию установил ScrollPane, полосы прокрутки (scroll) появятся когда содержание веб больше, чем регион отображения.

WebViewDemo.java
package org.o7planning.javafx.webview; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.VBox; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; public class WebViewDemo extends Application { @Override public void start(final Stage stage) { Button buttonURL = new Button("Load Page https://eclipse.org"); Button buttonHtmlString = new Button("Load HTML String"); Button buttonHtmlFile = new Button("Load File C:/test/a.html"); final WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); buttonURL.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { String url = "https://eclipse.org"; // Load a page from remote url. webEngine.load(url); } }); buttonHtmlString.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { String html = "<html><h1>Hello</h1><h2>Hello</h2></html>"; // Load HTML String webEngine.loadContent(html); } }); buttonHtmlFile.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { try { File file = new File("C:/test/a.html"); URL url = file.toURI().toURL(); // file:/C:/test/a.html System.out.println("Local URL: " + url.toString()); webEngine.load(url.toString()); } catch (MalformedURLException e) { e.printStackTrace(); } } }); VBox root = new VBox(); root.setPadding(new Insets(5)); root.setSpacing(5); root.getChildren().addAll(buttonURL, buttonHtmlString, buttonHtmlFile, browser); Scene scene = new Scene(root); stage.setTitle("JavaFX WebView (o7planning.org)"); stage.setScene(scene); stage.setWidth(450); stage.setHeight(300); stage.show(); } public static void main(String[] args) { launch(args); } }
Чтобы загрузить вебсайт на браузер требуется определенное время. Иногда вам нужно использовать ProgressBar чтобы отобразить процент загружения вебсайта.

WebViewWithProgressDemo.java
package org.o7planning.javafx.webview; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker; import javafx.concurrent.Worker.State; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ProgressBar; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; public class WebViewWithProgressDemo extends Application { @Override public void start(final Stage stage) { TextField addressBar = new TextField(); addressBar.setText("https://eclipse.org"); Button goButton = new Button("Go!"); Label stateLabel = new Label(); stateLabel.setTextFill(Color.RED); ProgressBar progressBar = new ProgressBar(); final WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); // A Worker load the page Worker<Void> worker = webEngine.getLoadWorker(); // Listening to the status of worker worker.stateProperty().addListener(new ChangeListener<State>() { @Override public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) { stateLabel.setText("Loading state: " + newValue.toString()); if (newValue == Worker.State.SUCCEEDED) { stage.setTitle(webEngine.getLocation()); stateLabel.setText("Finish!"); } } }); // Bind the progress property of ProgressBar // with progress property of Worker progressBar.progressProperty().bind(worker.progressProperty()); goButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { String url = addressBar.getText(); // Load the page. webEngine.load(url); } }); // VBox root = new VBox(); root.getChildren().addAll(addressBar, goButton, stateLabel, progressBar, browser); Scene scene = new Scene(root); stage.setTitle("JavaFX WebView (o7planning.org)"); stage.setScene(scene); stage.setWidth(450); stage.setHeight(300); stage.show(); } public static void main(String[] args) { launch(args); } }
После того как WebView загрузил вебсайт, вы можете интерактировать с вебсайтом из JavaFX. В примере ниже пользователь нажимает на Button в приложении JavaFX он вызывает функцию Javascript отображенной страницы на WebView.
// Enable Javascript. webEngine.setJavaScriptEnabled(true); // Call a JavaScript function of the current page webEngine.executeScript("changeBgColor();");A

WebViewExecuteJsDemo.java
package org.o7planning.javafx.webview; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.VBox; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; public class WebViewExecuteJsDemo extends Application { // A HTML Content with a javascript function. private static String HTML_STRING = // "<html>"// + "<head> " // + " <script language='javascript'> " // + " function changeBgColor() { "// + " var color= document.getElementById('color').value; "// + " document.body.style.backgroundColor= color; " // + " } " // + " </script> "// + "</head> "// + "<body> "// + " <h2>This is Html content</h2> "// + " <b>Enter Color:</b> "// + " <input id='color' value='yellow' /> "// + " <button onclick='changeBgColor();'>Change Bg Color</button> "// + "</body> "// + "</html> "// ; @Override public void start(final Stage stage) { Button button = new Button("Execute Javascript (Call from JavaFX)"); final WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); // Enable Javascript. webEngine.setJavaScriptEnabled(true); webEngine.loadContent(HTML_STRING); button.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { // Call a JavaScript function of the current page webEngine.executeScript("changeBgColor();"); } }); VBox root = new VBox(); root.setPadding(new Insets(5)); root.setSpacing(5); root.getChildren().addAll(button, browser); Scene scene = new Scene(root); stage.setTitle("JavaFX WebView (o7planning.org)"); stage.setScene(scene); stage.setWidth(450); stage.setHeight(300); stage.show(); } public static void main(String[] args) { launch(args); } }
Вы так же можете войти в объекты Javascript через объекты Java. Большинство объектов Javascript обернуты netscape.javascript.JSObject. Методы JSObject:
public Object call(String methodName, Object... args); public Object eval(String s); public Object getMember(String name); public void setMember(String name, Object value); public void removeMember(String name); public Object getSlot(int index); public void setSlot(int index, Object value);
Пример:
// Back Browser History webEngine.executeScript("history.back()"); // Or // Get the object representing the history of JavaScript objects JSObject. JSObject history = (JSObject) webEngine.executeScript("history"); // Call 'back' method, without parameter. history.call("back");
Особенный случай, когда при вызове JavaScript возвращается объект DOM (DOM Node). В данном случае, результат обернут объектом JSObject он выполняет интерфейс org.w3c.dom.Node.
Element p = (Element) ebEngine.executeScript("document.getElementById('para')"); p.setAttribute("style", "font-weight: bold");
Выше, вы могли вызвать функцию Javascript страницы отображенной на WebView из JavaFX. В обратном, вы так же можете создать вызовы Upcalls от Javascript до JavaFX.
Со стороны JavaFX, вам нужно создать объект интерфейса (лобого класса) и удостовериться, что он знаком для JavaScript через вызов JSObject.setMember(). После выполнения этого, вы можете вызвать методы public или поля public объекта Java от Javascript.
// A Bridge class and must a public class public class Bridge { public void showTime() { System.out.println("Show Time"); label.setText("Now is: " + df.format(new Date())); } } // Get window object of page. JSObject jsobj = (JSObject) webEngine.executeScript("window"); // Set member cho đối tượng 'window' jsobj.setMember("myJavaMember", new Bridge());
В странице HTML:
<!-- In HTML --> <button onclick='myJavaMember.showTime();'>Call To JavaFX</button>
Смотреть полный пример:

WebViewUpCallsDemo.java
package org.o7planning.javafx.webview; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker; import javafx.concurrent.Worker.State; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Label; 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 WebViewUpCallsDemo extends Application { private DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); private Label label; // A Bridge class and must a public class public class Bridge { public void showTime() { System.out.println("Show Time"); label.setText("Now is: " + df.format(new Date())); } } // A HTML Content with a javascript function. private static String HTML_STRING = // "<html>"// + "<head> " // + " <script language='javascript'> " // + " function callToJavaFX() { "// + " myJavaMember.showTime(); " // + " } " // + " </script> "// + "</head> "// + "<body> "// + " <h2>This is Html content</h2> "// + " <button onclick='callToJavaFX();'>Call To JavaFX</button> "// + "</body> "// + "</html> "// ; @Override public void start(final Stage stage) { label = new Label("-"); final WebView browser = new WebView(); final WebEngine webEngine = browser.getEngine(); // Enable Javascript. webEngine.setJavaScriptEnabled(true); // A Worker load the page Worker<Void> worker = webEngine.getLoadWorker(); // Listening to the status of worker worker.stateProperty().addListener(new ChangeListener<State>() { @Override public void changed(ObservableValue<? extends State> observable, // State oldValue, State newValue) { // When load successed. if (newValue == Worker.State.SUCCEEDED) { // Get window object of page. JSObject jsobj = (JSObject) webEngine.executeScript("window"); // Set member for 'window' object. // In Javascript access: window.myJavaMember.... jsobj.setMember("myJavaMember", new Bridge()); } } }); // Load HTML content. // Tải nội dung HTML webEngine.loadContent(HTML_STRING); VBox root = new VBox(); root.setPadding(new Insets(5)); root.setSpacing(5); root.getChildren().addAll(label, browser); Scene scene = new Scene(root); stage.setTitle("JavaFX WebView (o7planning.org)"); stage.setScene(scene); stage.setWidth(450); stage.setHeight(300); stage.show(); } public static void main(String[] args) { launch(args); } }