The document describes how to embed a visual component that displays content of web pages in Swing and JavaFX applications.

Embedding

JxBrowser can be used in Java applications built with the following Java GUI frameworks:

  • Swing
  • JavaFX

The Browser component itself is not a visual component that allows displaying web page. To display the content of a web page loaded in Browser please use one of the following controls, depending on the GUI framework used:

  • com.teamdev.jxbrowser.view.swing.BrowserView
  • com.teamdev.jxbrowser.view.javafx.BrowserView

Swing

To display the content of a web page in a Java Swing application create an instance of the com.teamdev.jxbrowser.view.swing.BrowserView:

import com.teamdev.jxbrowser.view.swing.BrowserView;
...
BrowserView view = BrowserView.newInstance(browser);

And embed it into a JFrame:

frame.add(view, BorderLayout.CENTER);

Here is the complete example:

import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;

import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.engine.EngineOptions;
import com.teamdev.jxbrowser.view.swing.BrowserView;
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public final class HelloWorld {

    public static void main(String[] args) {
        // Create and run Chromium engine.
        Engine engine = Engine.newInstance(
                EngineOptions.newBuilder(HARDWARE_ACCELERATED).build());

        Browser browser = engine.newBrowser();
        // Load the required web page.
        browser.navigation().loadUrl("https://html5test.com");

        SwingUtilities.invokeLater(() -> {
            // Create Swing component for rendering web content
            // loaded in the given Browser instance.
            BrowserView view = BrowserView.newInstance(browser);

            // Create and display Swing app frame.
            JFrame frame = new JFrame("JxBrowser AWT/Swing");
            // Close Engine and closing app frame.
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    engine.close();
                }
            });
            frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            frame.add(view, BorderLayout.CENTER);
            frame.setSize(800, 600);
            frame.setVisible(true);
        });
    }
}

The output of this example looks as follows: HTML5 Video

JavaFX

To display the content of a web page in a JavaFX application create an instance of the com.teamdev.jxbrowser.view.javafx.BrowserView:

import com.teamdev.jxbrowser.view.javafx.BrowserView;
...
BrowserView view = BrowserView.newInstance(browser);

And embed it into a Scene:

Scene scene = new Scene(new BorderPane(view), 800, 600);

Here is the complete example:

import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
import static com.teamdev.jxbrowser.os.Environment.isMac;

import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.engine.EngineOptions;
import com.teamdev.jxbrowser.view.javafx.BrowserView;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public final class HelloWorld extends Application {

    @Override
    public void start(Stage primaryStage) {
        // Create and run Chromium engine.
        Engine engine = Engine.newInstance(
                EngineOptions.newBuilder(HARDWARE_ACCELERATED).build());
        Browser browser = engine.newBrowser();
        // Load the https://html5test.com web page.
        browser.navigation().loadUrl("https://html5test.com");

        // Create UI component for rendering web content
        // loaded in the given Browser instance.
        BrowserView view = BrowserView.newInstance(browser);

        Scene scene = new Scene(new BorderPane(view), 800, 600);
        primaryStage.setTitle("JxBrowser JavaFX");
        primaryStage.setScene(scene);
        primaryStage.show();

        // Close the engine when stage is about to close.
        primaryStage.setOnCloseRequest(event -> close(engine));
    }

    private void close(Engine engine) {
        if (isMac()) {
            // On macOS the Engine instance must be closed in UI thread.
            engine.close();
        } else {
            // On Windows and Linux it must be closed in non-UI thread.
            new Thread(engine::close).start();
        }
    }
}

The output of this example looks as follows: HTML5 Video

JFXPanel

We recommend that you use Swing BrowserView in Swing applications as well as JavaFX BrowserView in JavaFX applications.

Sometimes you might need to embed JavaFX BrowserView into a Swing application. For example, if you develop a complex web browser control using JavaFX UI Toolkit and you have to display this JavaFX control in a Swing/AWT application.

Since 7.1 you can embed JavaFX BrowserView into a Swing/AWT window through javafx.embed.swing.JFXPanel. It is supported on all supported platforms with all rendering modes.

import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.engine.EngineOptions;
import com.teamdev.jxbrowser.engine.RenderingMode;
import com.teamdev.jxbrowser.view.javafx.BrowserView;
import java.awt.BorderLayout;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 * The example demonstrates how to embed JavaFX BrowserView into 
 * JFXPanel that is displayed inside Swing/AWT Frame.
 */
public final class JFXPanelExample {

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(JFXPanelExample::initAndShowGUI);
    }

    private static void initAndShowGUI() {
        JFrame frame = new JFrame("JFXPanel");

        // Embed JFXPanel into Swing Frame.
        JFXPanel fxPanel = new JFXPanel();
        frame.add(fxPanel, BorderLayout.CENTER);
        frame.setSize(600, 600);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Initialize JFXPanel in JavaFX UI Thread.
        Platform.runLater(() -> initFX(fxPanel));
    }

    private static void initFX(JFXPanel fxPanel) {
        Engine engine = Engine.newInstance(
                EngineOptions.newBuilder(RenderingMode.HARDWARE_ACCELERATED)
                        .build());

        Browser browser = engine.newBrowser();
        browser.navigation().loadUrl("https://www.google.com");
        // Create JavaFX BrowserView and insert it into JFXPanel.
        BrowserView view = BrowserView.newInstance(browser);
        BorderPane pane = new BorderPane(view);
        fxPanel.setScene(new Scene(pane, 600, 600));
    }
}

FXML

You can embed JavaFX BrowserView in an FXML app using the approach described in this section below.

First of all please describe the structure of the browser-view.fxml file to tell JavaFX how the BrowserView control should be embedded into the JavaFX application GUI.

<?xml version="1.0" encoding="UTF-8"?>

<?import com.teamdev.jxbrowser.view.javafx.FxmlBrowserView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane 
    fx:controller="com.teamdev.jxbrowser.view.javafx.FxmlBrowserViewController" 
    xmlns:fx="http://javafx.com/fxml">
    <top>
        <TextField fx:id="textField" text="https://www.google.com" 
            onAction="#loadUrl"/>
    </top>
    <center>
        <FxmlBrowserView fx:id="browserView"/>
    </center>
</BorderPane>

This FXML declares a component that consists of two elements: address bar and browser view. The address bar represents a simple text field. Here we can type a URL and hit Enter to load it in the browser view below. The browser view contains FxmlBrowserView that displays content of the loaded web page.

The implementation of FxmlBrowserViewController defined in the browser-view.fxml file looks like the following:

package com.teamdev.jxbrowser.view.javafx;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;

import java.net.URL;
import java.util.ResourceBundle;

/**
 * Represents FXML controller with the address bar and browser view area that
 * displays the URL entered in the address bar.
 */
public final class FxmlBrowserViewController implements Initializable {

    @FXML
    private TextField textField;

    @FXML
    private FxmlBrowserView browserView;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        browserView.browser().navigation().loadUrl(textField.getText());
    }

    public void loadUrl(ActionEvent actionEvent) {
        browserView.browser().navigation().loadUrl(textField.getText());
    }
}

You may notice that the controller implementation uses FxmlBrowserView instead of the JavaFX BrowserView. It is because JavaFX BrowserView does not provide the default public constructor, so it cannot be used in FXML directly. To embed the JavaFX BrowserView use FxmlBrowserView that represents a simple wrapper with the default public constructor that initializes and embeds JavaFX BrowserView.

The implementation of the FxmlBrowserView class is the following:

package com.teamdev.jxbrowser.view.javafx;

import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.engine.EngineOptions;
import com.teamdev.jxbrowser.engine.RenderingMode;
import javafx.scene.layout.StackPane;

/**
 * A wrapper component for JavaFX {@link BrowserView} that allows using
 * the BrowserView instance in FXML applications. The JavaFX BrowserView
 * cannot be used in FXML directly, because it does not provide the default
 * public constructor.
 */
public final class FxmlBrowserView extends StackPane {

    private final BrowserView view;

    /**
     * Constructs an instance of {@code FxmlBrowserView}.
     */
    public FxmlBrowserView() {
        Engine engine = Engine.newInstance(
                EngineOptions.newBuilder(RenderingMode.HARDWARE_ACCELERATED)
                        .build());
        view = BrowserView.newInstance(engine.newBrowser());
        getChildren().add(view);
    }

    /**
     * Returns the {@link Browser} instance of the current browser view.
     */
    public Browser browser() {
        return view.getBrowser();
    }
}

Now, we have everything to implement and run our FXML example:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

/**
 * This example demonstrates how to use JavaFX BrowserView in FXML app
 * through the {@link com.teamdev.jxbrowser.view.javafx.FxmlBrowserView} control.
 */
public final class BrowserViewInFxml extends Application {

    public static void main(String[] args) {
        Application.launch(BrowserViewInFxml.class, args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        BorderPane pane = FXMLLoader.load(
                BrowserViewInFxml.class.getResource("browser-view.fxml"));

        primaryStage.setTitle("JavaFX BrowserView in FXML");
        primaryStage.setScene(new Scene(pane, 1024, 600));
        primaryStage.show();
    }
}

Once you run this example you should get the following output:

FXML Example Output

The complete example with all the classes and resources used in this section you can find in JxBrowser Examples.

Rendering

JxBrowser supports several rendering modes. In this section we will describe each of the modes with their performance and limitations, and provide you with recommendations on choosing the right mode depending on the type of the Java application.

Hardware Accelerated

In this rendering mode the library renders the content of a web page using the GPU in Chromium GPU process and displays it directly on a surface. In this mode the BrowserView creates and embeds a native heavyweight window (surface) on which the library renders the produced pixels.

Off-Screen

In this rendering mode the library renders the content of a web page using the GPU in Chromium GPU process and copies the pixels to an off-screen buffer allocated in the Java process memory. In this mode the BrowserView creates and embeds a lightweight component that reads the pixels from the off-screen buffer and displays them using the standard Java Graphics API.

Performance

The rendering modes have different performance. For example, if we play an HTML5 video full screen (2880x1800) on MacBook Pro (15-inch, 2017) with the following hardware:

  • CPU: 2.9 GHz Intel Core i7
  • RAM: 16 GB 2133 MHz LPDDR3
  • GPU: Radeon Pro 560 4096 MB
  • Built-in Display: 15.4-inch (2880 x 1800)

the rendering performance in Frame Per Second (FPS) would be: Rendering Performance

Limitations

Mixing Heavyweight and Lightweight

Please do not embed the BrowserView into a JInternalFrame or JLayeredPane, or display other Swing components over the BrowserView when the HARDWARE_ACCELERATED rendering mode is enabled. In this mode BrowserView displays a native heavyweight window. Displaying a heavyweight window inside a lightweight component leads to a well-known issue with mixing heavyweight and lightweight components.

According to the article the issue with mixing the heavyweight and lightweight components has been fixed in JDK 6 Update 12 and JDK 7 build 19. It is true only for the Java Swing heavyweight components such as java.awt.Canvas. JxBrowser embeds its own heavyweight native widget. So, the fix will not be applied in this case.

JavaFX Layered Windows

Configuring a JavaFX Stage with the StageStyle.TRANSPARENT style adds the WS_EX_LAYERED window style flag to JavaFX window on Windows. This flag is used to create a layered window. The layered window is a window that draws its content off-screen. If we embed a native window into a layered window when the HARDWARE_ACCELERATED rendering mode is enabled, its content will not be painted because of the window types conflict.

Mouse, Keyboard, Touch, Drag and Drop

In the OFF_SCREEN rendering mode on Windows and Linux, and both HARDWARE_ACCELERATED and OFF_SCREEN modes on macOS, the mouse, keyboard, and touch events are processed on the Java side and forwarded to the Chromium engine. Right now Java does not provide a fully functional touch events support, so JxBrowser does not support some touch gestures in these rendering modes. The same limitation applies to the Drag and Drop (DnD) functionality. In these rendering modes DnD is processed using the Java API, so it does not work exactly like in Google Chrome. DnD supports only the predefined set of flavours.

Drag and Drop

By default drag and drop is enabled for both Swing and JavaFX BrowserView. To disable drag and drop use the following way:

browserView.dragAndDrop().disable();
Go Top