JavaFX WebView

时间:2020-01-09 10:36:43  来源:igfitidea点击:

JavaFX WebView(javafx.scene.web.WebView)组件能够在JavaFX应用程序中显示网页(HTML,CSS,SVG,JavaScript)。因此,JavaFX" WebView"是一个小型浏览器。当我们需要显示文档(例如帮助文本),新闻,博客文章或者其他需要在运行时从Web服务器下载的内容时," WebView"组件非常方便。

JavaFXWebView在内部使用WebKit开源浏览器引擎来渲染网页。

JavaFX WebView示例

WebView组件是JavaFX节点,因此它可以像也是Java节点的其他JavaFX组件一样包含在场景图中。这是一个简单的JavaFXWebView示例:

package com.Hyman.javafx;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class WebViewExample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    public void start(Stage primaryStage) {
        primaryStage.setTitle("JavaFX WebView Example");

        WebView webView = new WebView();

        webView.getEngine().load("http://google.com");

        VBox vBox = new VBox(webView);
        Scene scene = new Scene(vBox, 960, 600);

        primaryStage.setScene(scene);
        primaryStage.show();

    }
}

该示例显示了一个JavaFX应用程序,该应用程序创建了一个WebView,该WebView插入到JavaFX VBox布局组件中,该组件又被放置在JavaFX Stage中,该JavaFX Stage被设置在主要的Stage中。

WebView WebEngine

JavaFX WebView WebEngine(javafx.scene.web.WebEngine)是WebView用来加载要在WebView内部显示的数据的内部组件。为了使WebView WebEngine加载数据,必须首先从WebView获取WebEngine实例。

获取WebEngine

我们可以通过调用WebView getEngine()方法从WebView中获取WebEngine。这是一个从JavaFXWebView获取WebEngine的示例:

WebView webView = new WebView();

WebEngine webEngine = webView.getEngine();

加载网页

一旦从WebView获得WebEngine实例,就可以通过调用其load()方法加载数据。 load()方法将URL作为参数。这是通过WebEngine``load()方法加载网页的示例:

webEngine.load("http://google.com");

加载本地内容

WebView WebEngine也可以加载本地内容,这意味着直接在方法调用中提供的内容(不是通过Internet加载)。 WebEngine通过loadContent()方法加载本地内容。这是一个使用loadContent()在JavaFXWebView中加载本地包含的示例。

String content =
    "<!DOCTYPE html>Hello World!";

webEngine.loadContent(content, "text/html");

在上面的示例中,loadContent()调用的第一个参数是内容本身。在此示例中,它是Java String中包含的非常简单的HTML文档。

上例中对loadContent()调用的第二个参数是内容的内容类型(MIME类型)。由于我们正在加载HTML文档,因此标准的内容类型为text / html

重新加载内容

可以重新加载JavaFXWebView中当前加载的内容。我们可以使用WebEngine``reload()方法来实现。这是一个使用WebEngine``reload()方法在JavaFXWebView中重新加载内容的示例:

webEngine.reload();

WebView缩放

可以设置JavaFXWebView的缩放级别。例如,我们可以指定" WebView"应始终放大25%,或者缩小10%等。放大或者缩小都会缩放" WebView"内部显示的所有内容。我们可以通过setZoom()方法设置WebView缩放级别。这是设置JavaFXWebView缩放级别的示例:

webView.setZoom(1.25);  //zoom in 25%.

setZoom()方法采用double值。值1.0表示100%的缩放级别,表示没有缩放。值0.5表示50%的缩放比例,表示缩小到原始尺寸的50%。在上面的示例中,值1.25表示缩放比例为125%,表示放大直到原始尺寸的125%。

WebView字体比例

也可以只缩放JavaFX" WebView"内部显示的文本,而不缩放" WebView"内部显示的任何非文本内容(例如图像)。我们可以通过setFontScale()方法设置字体缩放属性。这是一个将JavaFX" WebView"中显示的文本放大25%(总计125%)的示例:

webView.setFontScale(1.25);

setFontScale()方法采用一个double参数来指定字体比例值。标度值为1.0表示不按比例放大或者缩小。值0.5表示缩小到一半大小,值2.0表示放大到两倍大小。

设置用户代理HTTP标头

我们可以设置" User-Agent" HTTP标头,该标头发送到" WebView"实例从中加载网页的Web服务器。我们可以通过WebEnginesetUserAgent()方法设置User-Agent HTTP标头。这是设置WebView的User-Agent HTTP标头的示例:

webEngine.setUserAgent("MyApp Web Browser 1.0");

我们无需设置User-AgentHTTP标头,但是我们可能希望将特定的应用程序显示为单独的浏览器。我们可能需要包括应用程序正在使用的WebKit版本。这使Web服务器有更好的机会针对其访客浏览器(包括浏览器)优化其网站。这是在User-Agent中包含JavaFX和WebKit版本的示例:

webEngine.setUserAgent("MyApp Web Browser 1.0 - AppleWebKit/555.99 JavaFX 8.0");

禁用WebView上下文菜单

JavaFX WebView具有默认上下文菜单(右键单击菜单),当我们在JavaFX应用程序中的WebView上单击鼠标右键(上下文单击)时,将显示该菜单。我们可以通过调用参数值为false的WebView setContextMenuEnabled()方法来禁用WebView上下文菜单。这是一个禁用JavaFXWebView的上下文菜单的示例:

webView.setContextMenuEnabled(false);

浏览记录

我们可以访问JavaFXWebView的浏览历史记录。浏览历史由用户在" WebView"内部浏览时访问过的页面组成。我们可以通过JavaFX WebView对象访问JavaFX WebView的浏览历史记录。我们调用WebEngine``getHistory()方法,然后返回WebHistory对象。这是一个从WebView对象WebEngine对象获取WebHistory对象的示例:

WebEngine webEngine = webView.getEngine();
WebHistory history = webEngine.getHistory();

一旦可以访问" WebHistory"对象,就可以开始检查和处理浏览历史记录。在以下各节中,我们将介绍如何操作。

浏览历史记录

我们可以通过调用WebHistory对象中的getEntries()方法来访问其浏览历史记录条目。这是一个从WebHistory对象获取浏览历史记录列表的示例:

ObservableList<WebHistory.Entry> entries = history.getEntries();

返回的列表是" WebHistory.Entry"对象的列表,可以检查这些对象以获取有关每个条目的信息。

循环浏览历史记录

我们可以访问保存在" WebHistory"对象中的浏览历史记录条目(访问的页面)。这是一个遍历JavaFXWebHistory对象的所有浏览历史记录条目的示例:

Iterator<WebHistory.Entry> iterator = entries.iterator();
while(iterator.hasNext()){
    WebHistory.Entry entry = iterator.next();
}

我们还可以使用for-each循环迭代浏览历史记录条目,如下所示:

for(WebHistory.Entry entry : entries){
    //do something with the entry
}

Web历史记录

" WebHistory.Entry"包含以下信息:

  • 网址
  • 标题
  • 上次访问日期

我们可以使用以下方法从WebHistory.Entry访问URL,标题和最后访问日期:

String url           = entry.getUrl();
String title         = entry.getTitle();
Date lastVisitedDate = entry.getLastVisitedDate();

历史上的前进与后退

一旦有了WebHistory对象的实例,我们就可以实际操作历史记录了。我们可以强制" WebView"在浏览历史记录中前进和后退。我们可以通过调用WebHistorygo()方法来实现。这是浏览历史记录中前进和后退的两个示例:

history.go(-1);
history.go( 1);

如果我们将负整数传递给go()方法,浏览器将在浏览历史记录中向后移动到当前显示页面之前访问的页面(URL)。

如果将正整数传递给go()方法,则将使WebView在浏览历史记录中向前移动一个条目。仅当用户已经访问了至少2页并从第一页退回时,该方法才有效。

当前历史条目索引

如果我们在浏览历史记录中来回移动了一点,我们可能会对查看当前历史记录条目在浏览历史记录中的索引感兴趣。我们可以通过WebHistory方法getCurrentIndex()方法查看当前浏览历史记录条目的索引。这是读取当前浏览历史记录条目的索引的示例:

int currentIndex = history.getCurrentIndex();

加载文档时侦听状态更改

当我们告诉WebEngine加载文档时,该文档会通过另一个线程在后台加载。我们可以侦听文档加载状态中的更改,因此可以在文档加载完成时收到通知。这是一个监听WebView``WebEngine的文档加载状态变化的示例:

webEngine.getLoadWorker().stateProperty().addListener(
    new ChangeListener() {
        @Override
        public void changed(ObservableValue observable, Object oldValue, Object newValue) {
            System.out.println("oldValue: " + oldValue);
            System.out.println("newValue: " + newValue);

            if (newValue == Worker.State.SUCCEEDED) {
                //document finished loading
            }
        }
    }
);

从Java执行JavaScript

可以执行嵌入Java的JavaFXWebView内HTML页面中嵌入的JavaScript。我们可以通过WebEngine`executeScript()方法在Java的WebView中执行JavaScript。这是从Java代码执行嵌入在" WebView"中的JavaScript的简单示例:

webEngine.executeScript("myFunction()");

executeScript()方法采用Java字符串作为参数,其中包含要执行的JavaScript。上面的示例调用了一个名为myFunction()的JavaScript函数。这个函数必须在上面的WebEngineWebView中显示的网页中定义。

从WebEngine侦听器执行

到目前为止,除非从WebEngine侦听器中调用executeScript(),否则我在从Java执行JavaScript函数时遇到了一些问题。这是一个在WebEngine侦听器中从Java执行JavaScript的示例:

webEngine.getLoadWorker().stateProperty().addListener(
    new ChangeListener() {
        @Override
        public void changed(ObservableValue observable, Object oldValue, Object newValue) {
            System.out.println("oldValue: " + oldValue);
            System.out.println("newValue: " + newValue);

            if (newValue != Worker.State.SUCCEEDED) {
                return;
            }
            System.out.println("Succeeded!");
            String hello = (String) webEngine.executeScript("myFunction()");
            System.out.println("hello: " + hello);
        }
    }
);

如果我们知道是什么原因引起了问题,或者为什么存在此"限制",不胜感激,请发送一封电子邮件进行解释:-)

JavaScript返回值

如果JavaScript函数返回一个值,则该值将被转换为Java数据类型,并从executeScript()方法返回。假设JavaScript函数myFunction()返回一个字符串。在这种情况下,Java字符串将从executeScript()方法中返回。这是捕获该String的样子:

String returnValue = (String) webEngine.executeScript("myFunction()");

下表显示了各种JavaScript返回类型将转换为哪些Java类型:

JavaScript类型Java类型
nullnull
booleanBoolean布尔值
int32Integer整数
numberDouble
stringString字符串
objectJSObject(netscape.javascript.JSObject

从JavaScript执行Java

也可以从JavaFXWebView内运行的JavaScript调用Java代码。为此,我们必须使Java对象可用于在" WebView"内部运行的JavaScript。最简单的方法是将Java对象设置为" WebView"中显示的文档中" window"对象的成员。这是完成的方式:

webEngine.getLoadWorker().stateProperty().addListener(
    new ChangeListener() {
        @Override
        public void changed(ObservableValue observable, Object oldValue, Object newValue) {
            if (newValue != Worker.State.SUCCEEDED) { return; }

            JSObject window = (JSObject) webEngine.executeScript("window");
            window.setMember("myObject", new MyObject());
        }
    }
);

上面的示例首先通过WebEngineexecuteScript()方法访问" window"对象。其次,该示例将MyObject类的实例设置为window对象的成员。现在,在WebView中运行的JavaScript可以在此对象上调用方法,就好像它是JavaScript对象一样。

MyObject类如下所示:

public static class MyObject {

    public void doIt() {
        System.out.println("doIt() called");
    }
}

将此类的对象公开为名为" myObject"的" window"对象的成员后,我们可以如下调用其doIt()方法:

window.myObject.doIt();

请记住,当文档首次加载到" WebView"中时," myObject"尚未在" window"对象上公开。因此,如果我们尝试立即对其调用方法,则该方法可能会失败。

访问DOM

我们可以通过调用WebEnginegetDocument()方法来访问JavaFX WebView内部显示的网页的DOM。这是访问WebView的DOM的示例:

Document document = webEngine.getDocument();

返回的Document对象是一个org.w3c.dom.Document实例。

网页CSS样式表

通常,网页会提供自己的CSS样式表。但是,如果网页没有CSS样式表,则可以使用WebEnginesetUserStyleSheetLocation()为其设置CSS样式表。这是一个使用WebEnginesetUserStyleSheetLocation()为网页设置CSS样式表的示例;

webEngine.setUserStyleSheetLocation("stylesheet.css");

作为参数传递给setUserStyleSheetLocation()方法的String应该是CSS样式表文件所在文件系统中的路径,

WebView CSS样式

可以使用CSS设置JavaFXWebView组件的样式,就像我们可以设置任何其他JavaFX组件的样式一样。我们可以为JavaFXWebView设置以下CSS属性:

CSS属性描述
-fx-context-menu-enabled接受“ true”或者“ false”的值-指定是否启用
上下文菜单(右键单击菜单)。
-fx-font-smoothing-type指定要应用的字体平滑类型。
-fx-font-scale十进制数字(例如1.4)设置此WebView的字体比例