JavaFX

JavaFX WebView Example

This is a JavaFX WebView Example. JavaFX provides a web component that can be used as an embedded web browser in a JavaFX application. It is based on WebKit, which is an open source web browser engine. It supports:

  • Viewing HTML5 content with CSS and JavaScript
  • Access to the DOM of the HTML content
  • Browsing history maintenance
  • Executing JavaScript code from JavaFX and vice versa

The component handles most of the work of web browsing, for example, rendering the HTML content, maintaining a history of the visited web pages, navigating to a URL when links are clicked, displaying pop-up contents, among others.

 
The web browser component comprises a simple API consisting of a few classes in the javafx.scene.web package:

  • WebView
  • WebEngine
  • WebHistory
  • WebHistory.Entry
  • WebEvent
  • PopupFeatures
  • PromptData

The WebView class inherits from the Parent class. It is a node, not a control. It is added to a Scene Graph for viewing web pages using local or remote URLs. A WebView displays one web page at a time and it can be styled using a CSS.

A WebView uses a WebEngine for the core processing of its content. A WebEngine manages one web page at a time. The WebView handles user input events such as mouse and keyboard events and other tasks, for example, loading the web page content, applying a CSS, and creating a DOM, that are performed by the WebEngine. When using a WebView component, you will be working with its WebEngine most of the time.

A WebEngine maintains the browsing history of all visited web pages for a session in an instance of the WebHistory class. An instance of the inner class WebHistory.Entry represents an entry in the browsing history. An instance of the WebEvent class represents an event generated by a WebEngine while it processes a web page.

The following table shows an overview of the whole article:

The following examples use Java SE 8 and JavaFX 2.2.

1. Creating a Web Browser Component

1.1 The Code

FxWebViewExample1.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import javafx.beans.value.ChangeListener;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.scene.web.WebEngine;
import static javafx.concurrent.Worker.State;
 
public class FxWebViewExample1 extends Application
{
    public static void main(String[] args)
    {
        Application.launch(args);
    }
     
    @Override
    public void start(final Stage stage)
    {
        // Create the WebView
        WebView webView = new WebView();
         
        // Create the WebEngine
        final WebEngine webEngine = webView.getEngine();
 
        // LOad the Start-Page
        webEngine.load("http://www.oracle.com");
         
        // Update the stage title when a new web page title is available
        webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>()
        {
            public void changed(ObservableValue<? extends State> ov, State oldState, State newState)
            {
                if (newState == State.SUCCEEDED)
                {
                    //stage.setTitle(webEngine.getLocation());
                    stage.setTitle(webEngine.getTitle());
                }
            }
        });
 
        // Create the VBox
        VBox root = new VBox();
        // Add the WebView to the VBox
        root.getChildren().add(webView);
 
        // Set the Style-properties of the VBox
        root.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");
 
        // Create the Scene
        Scene scene = new Scene(root);
        // Add  the Scene to the Stage
        stage.setScene(scene);
        // Display the Stage
        stage.show();
    }
}

An instance of the WebView class represents a web browser. The class contains only one constructor, which is a no-args constructor:

1
WebView webView = new WebView();

The constructor of the WebView class creates a WebEngine automatically and you cannot change it. The getEngine() method of the WebView class returns the reference of the WebEngine:

1
WebEngine webEngine = webView.getEngine();

A WebEngine can load content from a URL or a string in memory. You would use the load() method of the WebEngine class to load content from a URL. The URL is specified as a String. It can be a local or remote URL. You would use the reload() method of the WebEngine to reload the current page, as shown in the following code:

1
2
// Load the Google web page
webEngine.load("http://www.oracle.com");

WebEngine loads a web page asynchronously in the background threads using a Worker object. Submitting a request to load a web page before the previous request is fulfilled cancels the previous request. You can find the reference of the Worker object loading the web page using the getLoadWorker() method.

The following snippet of code sets the title of a successfully loaded web page as the title of the stage showing the WebView:

1
2
3
4
5
// Create the WebView
WebView webView = new WebView();
 
// Create the WebEngine
final WebEngine webEngine = webView.getEngine();

The WebEngine class contains a title property, which is updated at some point while a web page is being loaded. You can achieve the same effect as above by listening to the change in the title property of the WebEngine:

01
02
03
04
05
06
07
08
09
10
11
12
// Update the stage title when a new web page title is available
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>()
{
    public void changed(ObservableValue<? extends State> ov, State oldState, State newState)
    {
        if (newState == State.SUCCEEDED)
        {
                //stage.setTitle(webEngine.getLocation());
            stage.setTitle(webEngine.getTitle());
        }
    }
});

1.2 The GUI

The following image shows how to use a WebView component. When you run the program, it opens the web page at http://www.oracle.com.

A simple JavaFX WebView Example
A simple JavaFX WebView Example

2. Setting Properties for a WebView

2.1 The Code

FxWebViewExample2.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import javafx.beans.value.ChangeListener;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.scene.web.WebEngine;
 
public class FxWebViewExample2 extends Application
{
    public static void main(String[] args)
    {
        Application.launch(args);
    }
     
    @Override
    public void start(final Stage stage)
    {
        // Create the WebView
        WebView webView = new WebView();
         
        // Disable the context menu
        webView.setContextMenuEnabled(false);
         
        // Increase the text font size by 20%
        webView.setFontScale(1.20);
         
        // Set the Zoom 20%
        webView.setZoom(1.20);
         
        // Set font smoothing type to GRAY
        webView.setFontSmoothingType(FontSmoothingType.GRAY);
         
        // Create the WebEngine
        final WebEngine webEngine = webView.getEngine();
        // Load the StartPage
        webEngine.load("http://www.google.com");
         
        // Update the stage title when a new web page title is available       
        webEngine.titleProperty().addListener(new ChangeListener<String>()
        {
            public void changed(ObservableValue<? extends String> ov,
                    final String oldvalue, final String newvalue)
            {
                stage.setTitle(newvalue);
            }
        });
         
        // Create the VBox
        VBox root = new VBox();
        // Add the Children to the VBox
        root.getChildren().add(webView);
 
        // Set the Style-properties of the VBox
        root.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");
 
        // Create the Scene
        Scene scene = new Scene(root);
        // Add  the Scene to the Stage
        stage.setScene(scene);
        // Display the Stage
        stage.show();
    }
}

The WebView component comes with some built-in features. By default, it displays a context menu. The menu items in the context menu depend on the state of the component.

For example, it shows a Go Back menu item when you have navigated to pages other than the first page and shows a Stop Loading menu item when the page is still being loaded. The standard text editing menu items (Cut, Copy, and Paste) are shown when text is selected or focus is in a text-editing field. You can set the contextMenuEnabled property to false to disable the context menu:

1
2
// Disable the context menu
webView.setContextMenuEnabled(false);

You can apply a scale factor for text using the fontScale property. It uses a double value number. For example, to make the text font 10% larger, set it to 1.10, and to make the text font 40% smaller, set it to 0.60. The default value is 1.0. Changing this property affects only the text in the web page, not images and other fixed-size elements. The following code would increase the font by 20%:

1
2
// Increase the text font size by 20%
webView.setFontScale(1.20);

You can apply a zoom factor to the content in the WebView using the zoom property. It also uses a double value number, as explained above. The default value is 1.0. changing this property affects the entire content in WebView. The following code would change the zoom by 20%:

1
2
// Zoom 20%
webView.setZoom(1.20);

You can specify font smoothing of GRAY or LCD for onscreen text. The default value is LCD. The GRAY smoothing is suitable for graphics and animation. The LCD smoothing is suitable for small-sized text where legibility is important. A request for LCD text is treated as a hint, which may be ignored.

The fontSmoothingType property specifies the font smoothing type. The property value is one of the constants (GRAY and LCD) of the FontSmoothingType enum, which is in the javafx.scene.text package. The following code sets font smoothing:

1
2
// Set font smoothing type to GRAY
webView.setFontSmoothingType(FontSmoothingType.GRAY);

The WebView class contains several other properties, which are related to setting its minimum, preferred, and maximum width and height.

2.2 The GUI

The following GUI shows an example of using properties in a WebView.

A JavaFX WebView Example with Properties
A JavaFX WebView Example with Properties

3. Enhancing the Web Browser Application

3.1 The Code

WebMenu.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.ToggleGroup;
import javafx.scene.text.FontSmoothingType;
import javafx.scene.web.WebView;
 
public class WebMenu extends MenuButton
{
    public WebMenu(WebView webView)
    {
        // Set the Text of the WebMenu
        this.setText("Options");
         
        // Set the Style-properties of the Navigation Bar
        this.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");
         
        // Create the Menu Items
        CheckMenuItem ctxMenu = new CheckMenuItem("Enable Context Menu");
        ctxMenu.setSelected(true);
         
        MenuItem normalFontMenu = new MenuItem("Normal");
        MenuItem biggerFontMenu = new MenuItem("10% Bigger");
        MenuItem smallerFontMenu = new MenuItem("10% Smaller");
 
        MenuItem normalZoomMenu = new MenuItem("Normal");
        MenuItem biggerZoomMenu = new MenuItem("10% Bigger");
        MenuItem smallerZoomMenu = new MenuItem("10% Smaller");
         
        // Create the RadioMenuItems
        RadioMenuItem grayMenu = new RadioMenuItem("GRAY");
        grayMenu.setSelected(true);    
        RadioMenuItem lcdMenu = new RadioMenuItem("LCD");
         
        // Create the Menus
        Menu scalingMenu = new Menu("Font Scale");
        scalingMenu.textProperty().bind(new SimpleStringProperty("Font Scale ").concat(webView.fontScaleProperty().multiply(100.0)).concat("%"));
 
        Menu smoothingMenu = new Menu("Font Smoothing");
 
        Menu zoomMenu = new Menu("Zoom");
        zoomMenu.textProperty().bind(new SimpleStringProperty("Zoom ").concat(webView.zoomProperty().multiply(100.0)).concat("%"));
         
        // Add  the Items to the corresponding Menu
        scalingMenu.getItems().addAll(normalFontMenu, biggerFontMenu, smallerFontMenu);
        smoothingMenu.getItems().addAll(grayMenu, lcdMenu);
        zoomMenu.getItems().addAll(normalZoomMenu, biggerZoomMenu, smallerZoomMenu);
 
        // Create the ToggleGroup
        new ToggleGroup().getToggles().addAll(lcdMenu, grayMenu);  
         
        // Define the Event Handler
        normalFontMenu.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webView.setFontScale(1.0);
            }
        });
 
        biggerFontMenu.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webView.setFontScale(webView.getFontScale() + 0.10);
            }
        });
 
        smallerFontMenu.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webView.setFontScale(webView.getFontScale() - 0.10);
            }
        });
         
        grayMenu.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webView.setFontSmoothingType(FontSmoothingType.GRAY);
            }
        });
 
        lcdMenu.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webView.setFontSmoothingType(FontSmoothingType.LCD);
            }
        });
             
        normalZoomMenu.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webView.setZoom(1.0);
            }
        });
         
        biggerZoomMenu.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webView.setZoom(webView.getZoom() + 0.10);
            }
        });
         
        smallerZoomMenu.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webView.setZoom(webView.getZoom() - 0.10);
            }
        });
         
 
        webView.contextMenuEnabledProperty().bind(ctxMenu.selectedProperty());
         
        // Enabled JavaScript option
        CheckMenuItem scriptMenu = new CheckMenuItem("Enable JavaScript");
        scriptMenu.setSelected(true);
        webView.getEngine().javaScriptEnabledProperty().bind(scriptMenu.selectedProperty());
 
        // Add Menus to the WebMenu
        this.getItems().addAll(ctxMenu, scalingMenu, smoothingMenu, zoomMenu, new SeparatorMenuItem(), scriptMenu);
    }
}

NavigationBar.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import java.io.File;
import java.net.MalformedURLException;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.Priority;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
 
public class NavigationBar extends HBox
{
    // Create the FileChooser
    private FileChooser fileChooser = new FileChooser();
     
    public NavigationBar(WebView webView, String homePageUrl, boolean goToHomePage)
    {
        // Set Spacing
        this.setSpacing(4);
         
        // Set the Style-properties of the Navigation Bar
        this.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");
 
        // Create the Label
        Label label = new Label("History:");
         
        // Configure the FileChooser
        fileChooser.setTitle("Open Web Content");
        fileChooser.getExtensionFilters().addAll(new ExtensionFilter("HTML Files", "*.html", "*.htm"));
         
        // Create the WebEngine
        WebEngine webEngine = webView.getEngine();
         
        // Create the TextField
        TextField pageUrl = new TextField();
         
        // Create the Buttons
        Button refreshButton = new Button("Refresh");
        Button goButton = new Button("Go");
        Button homeButton = new Button("Home");
        Button openButton = new Button("Open");
         
        // Let the TextField grow horizontallly
        HBox.setHgrow(pageUrl, Priority.ALWAYS);
         
         
        // Add an ActionListener to navigate to the entered URL    
        pageUrl.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webEngine.load(pageUrl.getText());
            }
        });
         
        // Update the stage title when a new web page title is available       
        webEngine.locationProperty().addListener(new ChangeListener<String>()
        {
            public void changed(ObservableValue<? extends String> ov,
                    final String oldvalue, final String newvalue)
            {
                // Set the Title of the Stage
                pageUrl.setText(newvalue);
            }
        });
         
        // Add an ActionListener for the Refresh Button
        refreshButton.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webEngine.reload();
            }
        });
         
        // Add an ActionListener for the Go Button
        goButton.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webEngine.load(pageUrl.getText());
            }
        });
         
        // Add an ActionListener for the Home Button
        homeButton.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                webEngine.load(homePageUrl);
            }
        });
                 
        // Add an ActionListener for the Open Button
        openButton.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                File selectedFile = fileChooser.showOpenDialog(webView.getScene().getWindow());
                 
                if (selectedFile != null)
                {
                    try
                    {
                        webEngine.load(selectedFile.toURI().toURL().toExternalForm());
                    }
                    catch(MalformedURLException ex)
                    {
                        ex.printStackTrace();
                    }
                }
            }
        });
         
        // Add the Children to the Navigation Bar
        this.getChildren().addAll(label, pageUrl,goButton, refreshButton, homeButton, openButton);
         
        if (goToHomePage)
        {
            // Load the URL
            webEngine.load(homePageUrl);
        }
    }
}

FxWebViewExample3.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.MenuButton;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
 
public class FxWebViewExample3 extends Application
{
    public static void main(String[] args)
    {
        Application.launch(args);
    }
     
    @Override
    public void start(final Stage stage)
    {
        // Create the WebView
        WebView webView = new WebView();
     
        // Update the stage title when a new web page title is available
        webView.getEngine().titleProperty().addListener(new ChangeListener<String>()
        {
            public void changed(ObservableValue<? extends String> ov,
                    final String oldvalue, final String newvalue)
            {
                // Set the Title of the Stage
                stage.setTitle(newvalue);
            }
        });
         
        // Load the Google web page
        String homePageUrl = "http://www.google.com";
 
        // Create the WebMenu
        MenuButton menu = new WebMenu(webView);
         
        // Create the Navigation Bar
        NavigationBar navigationBar = new NavigationBar(webView, homePageUrl, true);
        // Add the children to the Navigation Bar
        navigationBar.getChildren().add(menu);
         
        // Create the VBox
        VBox root = new VBox(navigationBar, webView);
         
        // Set the Style-properties of the VBox
        root.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");
         
        // Create the Scene
        Scene scene = new Scene(root);
        // Add the Scene to the Stage
        stage.setScene(scene);
        // Display the Stage
        stage.show();      
    }
}

In the class FxWebViewExample1.java, you had a very basic web browser. Let’s enhance that browser to allow users to specify a URL and set options at runtime. The above class creates a WebOptionsMenu class for setting options for a WebView. It inherits from the MenuButton class. The constructor takes a WebView as an argument.

Now let’s create a reusable component for entering the URL of a new page. The code in the above Class creates a navigation bar. It boxes all the controls in an VBox. You need to pass the WebView for which the navigation will work, a home page URL, and a flag to indicate whether you want to navigate to the home page.

The buttons on the navigation bar have the following functions:

  • Enter a URL and press the Enter key to open the page or enter a URL and click the Go button to go to the page.
  • Click the Refresh button to reload the current page.
  • Click the Home button to go to the home page.
  • Click the Open button to open an HTML file from the local file system.

Enter a URL and press the Enter key to open the page or enter a URL and click the Go button to go to the page.

With the NavigationBar and WebMenu classes, you can develop a basic web browser writing a few lines of code. The program in the above class assembles the web browser components to build a basic web browser. It displays a window with a navigation bar, options, and a WebView. You would use the navigation bar to open any local or remote web page. Later you will enhance this program to show the browsing history and add Back and Forward buttons.

3.2 The GUI

The following image displays a window with a navigation bar, options, and a WebView. You would use the navigation bar to open any local or remote web page.

An enhanced JavaFX WebView Example
An enhanced JavaFX WebView Example

4. Accessing Browsing History

4.1 The Code

BrowserHistory.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebHistory;
import javafx.scene.web.WebHistory.Entry;
import javafx.scene.web.WebView;
import javafx.util.Callback;
 
public class BrowserHistory extends HBox
{
    public BrowserHistory(WebView webView)
    {
        // Set Spacing
        this.setSpacing(4);
         
        // Set the Style-properties of the Navigation Bar
        this.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");
 
        // Create the WebHistory
        WebHistory history = webView.getEngine().getHistory();
         
        // Create the Label
        Label label = new Label("History:");
         
        // Create the Buttons
        Button backButton = new Button("Back");
        backButton.setDisable(true);
        Button forwardButton = new Button("Forward");
        forwardButton.setDisable(true);
         
        // Add an ActionListener to the Back and Forward Buttons
        backButton.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                history.go(-1);
            }
        });
         
        forwardButton.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                history.go(1);
            }
        });
         
        // Add an ChangeListener to the currentIndex property
        history.currentIndexProperty().addListener(new ChangeListener<Number>()
        {
            public void changed(ObservableValue<? extends Number> ov,
                    final Number oldvalue, final Number newvalue)
            {
                int currentIndex = newvalue.intValue();
                 
                if (currentIndex <= 0)
                {
                    backButton.setDisable(true);
                }
                else
                {
                    backButton.setDisable(false);
                }
                 
                if (currentIndex >= history.getEntries().size())
                {
                    forwardButton.setDisable(true);
                }
                else
                {
                    forwardButton.setDisable(false);
                }
            }
        });    
 
         
        // Create the ComboBox for the History List
        ComboBox<Entry> historyList = new ComboBox<>();
        historyList.setPrefWidth(150);
        historyList.setItems(history.getEntries());
         
        // Set a cell factory to to show only the page title in the history list
        historyList.setCellFactory(new Callback<ListView<WebHistory.Entry>, ListCell<WebHistory.Entry>>()
        {
            @Override public ListCell<WebHistory.Entry> call(ListView<WebHistory.Entry> list)
            {
                ListCell<Entry> cell = new ListCell<Entry>()
                {
                    @Override
                    public void updateItem(Entry item, boolean empty)
                    {
                        super.updateItem(item, empty);
                     
                        if (empty)
                        {
                            this.setText(null);
                            this.setGraphic(null);
                        }
                        else
                        {
                            String pageTitle = item.getTitle();
                            this.setText(pageTitle);
                        }
                    }
                };
             
                return cell;               
            }
        });
                 
         
        // Let the user navigate to a page using the history list
        historyList.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent event)
            {
                int currentIndex = history.getCurrentIndex();
                 
                Entry selectedEntry = historyList.getValue();
                 
                int selectedIndex = historyList.getItems().indexOf(selectedEntry);
                int offset = selectedIndex - currentIndex;
                history.go(offset);            
            }
        });
         
        // Add the Children to the BrowserHistory
        this.getChildren().addAll(backButton, forwardButton, label,historyList);
    }
}

FxWebViewExample4.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import javafx.beans.value.ChangeListener;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.MenuButton;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
 
public class FxWebViewExample4 extends Application
{
    public static void main(String[] args)
    {
        Application.launch(args);
    }
     
    @Override
    public void start(final Stage stage)
    {
        // Create the WebView
        WebView webView = new WebView();
     
        // Update the stage title when a new web page title is available
        webView.getEngine().titleProperty().addListener(new ChangeListener<String>()
        {
            public void changed(ObservableValue<? extends String> ov,
                    final String oldvalue, final String newvalue)
            {
                // Set the Title of the Stage
                stage.setTitle(newvalue);
            }
        });
         
        // Load the Google web page
        String homePageUrl = "http://www.google.com";
 
        // Create the WebMenu
        MenuButton menu = new WebMenu(webView);
 
        // Create the Browser History
        BrowserHistory history = new BrowserHistory(webView);
         
        // Create the Navigation Bar
        NavigationBar navigationBar = new NavigationBar(webView, homePageUrl, true);
        // Add the Children to the Navigation Bar
        navigationBar.getChildren().addAll(menu,history);
         
        // Create the VBox
        VBox root = new VBox(navigationBar, webView);
         
        // Set the Style-properties of the VBox
        root.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");
         
        // Create the Scene
        Scene scene = new Scene(root);
        // Add the Scene to the Stage
        stage.setScene(scene);
        // Display the Stage
        stage.show();      
    }
}

The WebEngine maintains the browsing history for a session. An instance of the WebHistory class represents the browsing history, which maintains an observable list of visited web pages as instances of the inner class WebHistory.Entry. You would use the getHistory() method of the WebEngine class to get its history object. The getEntries() method of a WebHistory returns an ObservableList<Entry>. The entries in the list are arranged from oldest to newest, that is, the first entry in the list is the page visited first.

An Entry provides the title, URL, and the last visited date of the visited page through its getTitle(), getUrl(), and getLastVisitedDate() methods, respectively.

WebHistory has two properties:

  • currentIndex
  • maxSize

The currentIndex is a read-only int property that specifies the index of the current page in the list of visited pages. It changes as you visit different pages. The maxSize property specifies how many visited pages to keep in the history. The default is 100.

The go(int offset) method of the WebHistory class navigates the WebEngine to the Entry object at the (currentIndex + offset) location in the list of visited web pages. For example, go(-1) and go(1) have the same effect as clicking the Back and Forward buttons, respectively, in a web browser. The go(0) call is ignored. The offset value must be between zero and (size - 1), which is the size of the number of entries in the WebHistory. Otherwise, an IndexOutOfBoundsException is thrown.

The following snippet of code shows how to add the history-related controls to the navigation bar.

01
02
03
04
05
06
07
08
09
10
// Create the WebMenu
MenuButton menu = new WebMenu(webView);
 
// Create the Browser History
BrowserHistory history = new BrowserHistory(webView);
 
// Create the Navigation Bar
NavigationBar navigationBar = new NavigationBar(webView, homePageUrl, true);
// Add the Children to the Navigation Bar
navigationBar.getChildren().addAll(menu,history);

4.2 The GUI

The following GUI shows a WebView with a browser history:

A JavaFX WebView Example with History
A JavaFX WebView Example with History

5. Download

This was an example of javafx.scene.web.WebView

Download
You can download the full source code of this example here: JavaFxWebViewExample.zip

Andreas Pomarolli

Andreas has graduated from Computer Science and Bioinformatics at the University of Linz. During his studies he has been involved with a large number of research projects ranging from software engineering to data engineering and at least web engineering. His scientific focus includes the areas of software engineering, data engineering, web engineering and project management. He currently works as a software engineer in the IT sector where he is mainly involved with projects based on Java, Databases and Web Technologies.
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button