Documentation



JavaFX: Adding HTML Content to JavaFX Applications

9 Printing HTML Content

This chapter teaches you how to print a web page loaded in the WebView component.

With the printing API available in JavaFX 8, you can print graphical content of JavaFX applications. The corresponding classes and enums are located in the javafx.print package.

Using the Printing API

To enable the printing functionality in your JavaFX application, you must use the PrinterJob class. This class represents a printer job that is associated with the default system printer. Use the Printer class to alter a printer for a particular job. For each print job, you can specify job settings by using the properties of the JobSettings class such as collation, copies, pageLayout, pageRanges, paperSource, printColor, printResolution, printQuality, and printSides.

You can print any node of the scene graph including the root node. You can also print nodes that are not added to the scene. Use the printPage method to initiate a print job for a particular node: job.printPage(node). See the to JavaFX 8 API specification for more information about printing capabilities.

When working with the JavaFX web component, you typically need to print an HTML page loaded into the browser rather than the application UI itself. That is why the print method was added to the WebEngine class. This method is geared toward printing an HTML page that is associated with the web engine.

Adding a Context Menu to Enable Printing

Typically, you add a Print command to an application menu or assign printing to one of the toolbar buttons. In the WebViewSample application, the toolbar is overloaded with controls, which is why you add the Print command to the context menu that is enabled by a right-click. Example 9-1 shows a code fragment that adds a context menu with the Print command to the application toolbar.

Example 9-1 Creating a Toolbar Context Menu

//adding context menu
final ContextMenu cm = new ContextMenu();
MenuItem cmItem1 = new MenuItem("Print");
cm.getItems().add(cmItem1);
toolBar.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
    if (e.getButton() == MouseButton.SECONDARY) {
        cm.show(toolBar, e.getScreenX(), e.getScreenY());
    }
});

When you add the code fragment from Example 9-1 to the WebViewSample application, run it, and right click the toolbar, the Print context menu appears, as shown in Figure 9-1.

Figure 9-1 Print Context Menu

Description of Figure 9-1 follows
Description of "Figure 9-1 Print Context Menu"

Processing a Print Job

After the Print context menu is added to the application UI, you can define the printing action. First, you must create a PrinterJob object. Then, you call the WebEngine.print method passing the printer job as a parameter, as shown in Example 9-2.

Example 9-2 Calling the WebEngine.print Method

//processing print job
cmItem1.setOnAction((ActionEvent e) -> {
    PrinterJob job = PrinterJob.createPrinterJob();
    if (job != null) {
        webEngine.print(job);
        job.endJob();
    }
});

It is important to check for non-null printer jobs, because the createPrinterJob method returns null if there are no printers available in the system.

Study Example 9-3 to evaluate the complete code of the WebViewSample application with the enabled printing functionality.

Example 9-3 WebViewSample With the Enabled Printing Functionality

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener.Change;
import javafx.concurrent.Worker.State;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.print.PrinterJob;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.web.PopupFeatures;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebHistory;
import javafx.scene.web.WebHistory.Entry;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
 
public class WebViewSample extends Application {
 
    private Scene scene;
 
    @Override
    public void start(Stage stage) {
        // create scene
        stage.setTitle("Web View Sample");
        scene = new Scene(new Browser(stage), 900, 600, Color.web("#666970"));
        stage.setScene(scene);
        // apply CSS style
        scene.getStylesheets().add("webviewsample/BrowserToolbar.css");
        // show stage
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
}
 
class Browser extends Region {
 
    private final HBox toolBar;
    final private static String[] imageFiles = new String[]{
        "product.png",
        "blog.png",
        "documentation.png",
        "partners.png",
        "help.png"
    };
    final private static String[] captions = new String[]{
        "Products",
        "Blogs",
        "Documentation",
        "Partners",
        "Help"
    };
    final private static String[] urls = new String[]{
        "http://www.oracle.com/products/index.html",
        "http://blogs.oracle.com/",
        "http://docs.oracle.com/javase/index.html",
        "http://www.oracle.com/partners/index.html",
        WebViewSample.class.getResource("help.html").toExternalForm()
    };
    final ImageView selectedImage = new ImageView();
    final Hyperlink[] hpls = new Hyperlink[captions.length];
    final Image[] images = new Image[imageFiles.length];
    final WebView browser = new WebView();
    final WebEngine webEngine = browser.getEngine();
    final Button toggleHelpTopics = new Button("Toggle Help Topics");
    final WebView smallView = new WebView();
    final ComboBox comboBox = new ComboBox();
    private boolean needDocumentationButton = false;
    
    public Browser(final Stage stage) {
        //apply the styles
        getStyleClass().add("browser");
                
        for (int i = 0; i < captions.length; i++) {
            // create hyperlinks
            Hyperlink hpl = hpls[i] = new Hyperlink(captions[i]);
            Image image = images[i]
                    = new Image(getClass().getResourceAsStream(imageFiles[i]));
            hpl.setGraphic(new ImageView(image));
            final String url = urls[i];
            final boolean addButton = (hpl.getText().equals("Help"));  
            
            // process event 
            hpl.setOnAction((ActionEvent e) -> {
                needDocumentationButton = addButton;
                webEngine.load(url);
            });
                    
        }
 
 
        comboBox.setPrefWidth(60);
 
        // create the toolbar
        toolBar = new HBox();
        toolBar.setAlignment(Pos.CENTER);
        toolBar.getStyleClass().add("browser-toolbar");
        toolBar.getChildren().add(comboBox);
        toolBar.getChildren().addAll(hpls);
        toolBar.getChildren().add(createSpacer());
 
        //set action for the button
        toggleHelpTopics.setOnAction((ActionEvent t) -> {
            webEngine.executeScript("toggle_visibility('help_topics')");
        });
 
        smallView.setPrefSize(120, 80);
 
        //handle popup windows
        webEngine.setCreatePopupHandler(
                (PopupFeatures config) -> {
                    smallView.setFontScale(0.8);
                    if (!toolBar.getChildren().contains(smallView)) {
                        toolBar.getChildren().add(smallView);
                    }
                    return smallView.getEngine();
        });
 
        //process history
        final WebHistory history = webEngine.getHistory();
        history.getEntries().addListener(
            (Change<? extends Entry> c) -> {
                c.next();
                c.getRemoved().stream().forEach((e) -> {
                comboBox.getItems().remove(e.getUrl());
            });
                c.getAddedSubList().stream().forEach((e) -> {
                comboBox.getItems().add(e.getUrl());
            });
        });
 
        //set the behavior for the history combobox               
        comboBox.setOnAction((Event ev) -> {
            int offset
                    = comboBox.getSelectionModel().getSelectedIndex()
                    - history.getCurrentIndex();
            history.go(offset);
        });
 
        // process page loading
        webEngine.getLoadWorker().stateProperty().addListener(
            (ObservableValue<? extends State> ov, State oldState, 
                State newState) -> {
                    toolBar.getChildren().remove(toggleHelpTopics);
                    if (newState == State.SUCCEEDED) {
                        JSObject win
                                = (JSObject) webEngine.executeScript("window");
                        win.setMember("app", new JavaApp());
                        if (needDocumentationButton) {
                            toolBar.getChildren().add(toggleHelpTopics);
                        }
                    }
        });
        //adding context menu
        final ContextMenu cm = new ContextMenu();
        MenuItem cmItem1 = new MenuItem("Print");
        cm.getItems().add(cmItem1);
        toolBar.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent e) -> {
            if (e.getButton() == MouseButton.SECONDARY) {
                cm.show(toolBar, e.getScreenX(), e.getScreenY());
            }
        });
 
        //processing print job
        cmItem1.setOnAction((ActionEvent e) -> {
            PrinterJob job = PrinterJob.createPrinterJob();
            if (job != null) {
                webEngine.print(job);
                job.endJob();
            }
        });
 
        // load the home page        
        webEngine.load("http://www.oracle.com/products/index.html");
 
        //add components
        getChildren().add(toolBar);
        getChildren().add(browser);
    }
 
    // JavaScript interface object
    public class JavaApp {
 
        public void exit() {
            Platform.exit();
        }
    }
 
    private Node createSpacer() {
        Region spacer = new Region();
        HBox.setHgrow(spacer, Priority.ALWAYS);
        return spacer;
    }
 
    @Override
    protected void layoutChildren() {
        double w = getWidth();
        double h = getHeight();
        double tbHeight = toolBar.prefHeight(w);
        layoutInArea(browser,0,0,w,h-tbHeight,0,HPos.CENTER,VPos.CENTER);
        layoutInArea(toolBar,0,h-tbHeight,w,tbHeight,0,HPos.CENTER,VPos.CENTER);
    }
 
    @Override
    protected double computePrefWidth(double height) {
        return 900;
    }
 
    @Override
    protected double computePrefHeight(double width) {
        return 600;
    }
}

To extend the printing capabilities of the WebViewSample application, use the classes available in the javafx.print package.

In your JavaFX application, you can implement browser tabs by using the TabPane class and create a new WebView object when a user adds a new tab.

To further enhance this application, you can apply effects, transformations, and animated transitions. You can also add more WebView instances to the application scene.

See the JavaFX API documentation and the JavaFX CSS specification for more information about available features. You can also study the JavaFX in Swing tutorial to learn how to add a WebView component in your existing Swing application.

Related API Documentation 

  • WebView

  • WebEngine

  • WebHistory

  • Region

  • Hyperlink

  • Worker

Close Window

Table of Contents

JavaFX: Adding HTML Content to JavaFX Applications

Expand | Collapse