BrowserView
The document describes how to embed a visual component that displays content of web pages in Swing, JavaFX, SWT, and Compose Desktop applications.
Overview
JxBrowser can be used in Java applications built with the following Java GUI frameworks:
- Swing
- JavaFX
- Compose Desktop
- SWT
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
com.teamdev.jxbrowser.view.compose.BrowserView
com.teamdev.jxbrowser.view.swt.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);
import com.teamdev.jxbrowser.view.swing.BrowserView
...
val view = BrowserView.newInstance(browser)
And embed it into a JFrame
:
frame.add(view, BorderLayout.CENTER);
frame.add(view, BorderLayout.CENTER)
Here is the complete example:
import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.view.swing.BrowserView;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
/**
* The simplest application with the integrated browser component.
*
* <p>This example demonstrates:
*
* <ol>
* <li>Creating an instance of {@link Engine}.
* <li>Creating an instance of {@link Browser}.
* <li>Embedding the browser into Swing via {@link BrowserView}.
* <li>Loading the "https://html5test.teamdev.com" website.
* </ol>
*/
public final class BrowserViewSwing {
public static void main(String[] args) {
// Creating and running Chromium engine.
Engine engine = Engine.newInstance(HARDWARE_ACCELERATED);
Browser browser = engine.newBrowser();
// Loading the required web page.
browser.navigation().loadUrl("https://html5test.teamdev.com");
SwingUtilities.invokeLater(() -> {
// Creating a Swing component for rendering web content
// loaded in the given Browser instance.
BrowserView view = BrowserView.newInstance(browser);
// Creating and displaying Swing app frame.
JFrame frame = new JFrame("JxBrowser AWT/Swing");
// Closing the engine when the app frame is about to close.
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);
});
}
}
import com.teamdev.jxbrowser.browser.Browser
import com.teamdev.jxbrowser.dsl.Engine
import com.teamdev.jxbrowser.dsl.browser.navigation
import com.teamdev.jxbrowser.engine.Engine
import com.teamdev.jxbrowser.engine.RenderingMode
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
/**
* The simplest application with the integrated browser component.
*
* This example demonstrates:
*
* 1. Creating an instance of [Engine].
* 2. Creating an instance of [Browser].
* 3. Embedding the browser into Swing via [BrowserView].
* 4. Loading the "https://html5test.teamdev.com" website.
*/
fun main() {
// Creating and running Chromium engine.
val engine = Engine(RenderingMode.HARDWARE_ACCELERATED)
val browser = engine.newBrowser()
// Loading the required web page.
browser.navigation.loadUrl("https://html5test.teamdev.com")
SwingUtilities.invokeLater {
// Creating a Swing component for rendering web content
// loaded in the given Browser instance.
val view = BrowserView.newInstance(browser)
// Creating and displaying Swing app frame.
val frame = JFrame("JxBrowser AWT/Swing")
// Closing the engine when the app frame is about to close.
frame.addWindowListener(object: WindowAdapter() {
override fun windowClosing(e: WindowEvent) {
engine.close()
}
})
frame.defaultCloseOperation = WindowConstants.DISPOSE_ON_CLOSE
frame.add(view, BorderLayout.CENTER)
frame.setSize(800, 600)
frame.isVisible = true
}
}
The output of this example looks as follows:
See also our video tutorial that shows how to add BrowserView
to a Java Swing application:
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);
import com.teamdev.jxbrowser.view.javafx.BrowserView
...
val view = BrowserView.newInstance(browser)
And embed it into a Scene
:
Scene scene = new Scene(new BorderPane(view), 800, 600);
val scene = Scene(BorderPane(view), 800.0, 600.0)
Here is the complete example:
import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.view.javafx.BrowserView;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
/**
* The simplest application with the integrated browser component.
*
* <p>This example demonstrates:
*
* <ol>
* <li>Creating an instance of {@link Engine}.
* <li>Creating an instance of {@link Browser}.
* <li>Embedding the browser into JavaFX via {@link BrowserView}.
* <li>Loading the "https://html5test.teamdev.com" website.
* </ol>
*/
public final class BrowserViewJavaFx extends Application {
@Override
public void start(Stage primaryStage) {
// Creating and running Chromium engine.
Engine engine = Engine.newInstance(HARDWARE_ACCELERATED);
Browser browser = engine.newBrowser();
// Loading the required web page.
browser.navigation().loadUrl("https://html5test.teamdev.com");
// Creating a 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();
// Closing the engine when the stage is about to close.
primaryStage.setOnCloseRequest(event -> engine.close());
}
}
import com.teamdev.jxbrowser.browser.Browser
import com.teamdev.jxbrowser.dsl.Engine
import com.teamdev.jxbrowser.dsl.browser.navigation
import com.teamdev.jxbrowser.engine.Engine
import com.teamdev.jxbrowser.engine.RenderingMode
import com.teamdev.jxbrowser.view.javafx.BrowserView
import javafx.application.Application
import javafx.event.EventHandler
import javafx.scene.Scene
import javafx.scene.layout.BorderPane
import javafx.stage.Stage
/**
* The simplest application with the integrated browser component.
*
* This example demonstrates:
*
* 1. Creating an instance of [Engine].
* 2. Creating an instance of [Browser].
* 3. Embedding the browser into JavaFX via [BrowserView].
* 4. Loading the "https://html5test.teamdev.com" website.
*/
class HelloWorld : Application() {
override fun start(primaryStage: Stage) {
// Creating and running Chromium engine.
val engine = Engine(RenderingMode.HARDWARE_ACCELERATED)
val browser = engine.newBrowser()
// Loading the required web page.
browser.navigation.loadUrl("https://html5test.teamdev.com")
// Creating a UI component for rendering web content
// loaded in the given Browser instance.
val view = BrowserView.newInstance(browser)
val scene = Scene(BorderPane(view), 800.0, 600.0)
primaryStage.title = "JxBrowser JavaFX"
primaryStage.scene = scene
primaryStage.show()
// Closing the engine when the stage is about to close.
primaryStage.onCloseRequest = EventHandler { engine.close() }
}
}
The output of this example looks as follows:
See also our video tutorial that shows how to add BrowserView
to a JavaFX application:
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.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");
// Embedding 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);
// Initializing JFXPanel in JavaFX UI Thread.
Platform.runLater(() -> initFX(fxPanel));
}
private static void initFX(JFXPanel fxPanel) {
Engine engine = Engine.newInstance(RenderingMode.HARDWARE_ACCELERATED);
Browser browser = engine.newBrowser();
browser.navigation().loadUrl("https://www.google.com");
// Creating JavaFX BrowserView and inserting it into JFXPanel.
BrowserView view = BrowserView.newInstance(browser);
BorderPane pane = new BorderPane(view);
fxPanel.setScene(new Scene(pane, 600, 600));
}
}
import com.teamdev.jxbrowser.dsl.Engine
import com.teamdev.jxbrowser.dsl.browser.navigation
import com.teamdev.jxbrowser.engine.RenderingMode
import com.teamdev.jxbrowser.view.javafx.BrowserView
import javafx.application.Platform
import javafx.embed.swing.JFXPanel
import javafx.scene.Scene
import javafx.scene.layout.BorderPane
import java.awt.BorderLayout
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.
*/
fun main() = SwingUtilities.invokeLater {
initAndShowGUI()
}
private fun initAndShowGUI() {
val frame = JFrame("JFXPanel")
// Embedding JFXPanel into Swing Frame.
val fxPanel = JFXPanel()
frame.add(fxPanel, BorderLayout.CENTER)
frame.setSize(600, 600)
frame.isVisible = true
frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
// Initializing JFXPanel in JavaFX UI Thread.
Platform.runLater {
initFX(fxPanel)
}
}
private fun initFX(fxPanel: JFXPanel) {
val engine = Engine(RenderingMode.HARDWARE_ACCELERATED)
val browser = engine.newBrowser()
browser.navigation.loadUrl("https://www.google.com")
// Creating JavaFX BrowserView and inserting it into JFXPanel.
val view = BrowserView.newInstance(browser)
val pane = BorderPane(view)
fxPanel.scene = Scene(pane, 600.0, 600.0)
}
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:
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());
}
}
import com.teamdev.jxbrowser.dsl.browser.navigation
import javafx.event.ActionEvent
import javafx.fxml.FXML
import javafx.fxml.Initializable
import javafx.scene.control.TextField
import java.net.URL
import java.util.*
/**
* Represents FXML controller with the address bar and browser view area that
* displays the URL entered in the address bar.
*/
class FxmlBrowserViewController : Initializable {
@FXML
private val textField = TextField()
@FXML
private val browserView = FxmlBrowserView()
override fun initialize(location: URL, resources: ResourceBundle) {
browserView.browser().navigation.loadUrl(textField.text)
}
fun loadUrl(actionEvent: ActionEvent) {
browserView.browser().navigation.loadUrl(textField.text)
}
}
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:
import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.engine.RenderingMode;
import com.teamdev.jxbrowser.view.javafx.BrowserView;
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 Browser browser;
/**
* Constructs an instance of {@code FxmlBrowserView}.
*/
public FxmlBrowserView() {
Engine engine = Engine.newInstance(RenderingMode.HARDWARE_ACCELERATED);
browser = engine.newBrowser();
BrowserView view = BrowserView.newInstance(browser);
getChildren().add(view);
}
/**
* Returns the {@link Browser} instance of the current browser view.
*/
public Browser browser() {
return browser;
}
}
import com.teamdev.jxbrowser.browser.Browser
import com.teamdev.jxbrowser.dsl.Engine
import com.teamdev.jxbrowser.engine.RenderingMode
import com.teamdev.jxbrowser.view.javafx.BrowserView
import javafx.scene.layout.StackPane
/**
* A wrapper component for JavaFX [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.
*/
class FxmlBrowserView : StackPane() {
private val browser: Browser
/**
* Constructs an instance of `FxmlBrowserView`.
*/
init {
val engine = Engine(RenderingMode.HARDWARE_ACCELERATED)
browser = engine.newBrowser()
val view = BrowserView.newInstance(browser)
children.add(view)
}
/**
* Returns the [Browser] instance of the current browser view.
*/
fun browser() = browser
}
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 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();
}
}
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 [FxmlBrowserView] control.
*/
class BrowserViewInFxml : Application() {
override fun start(primaryStage: Stage) {
val pane = FXMLLoader.load<BorderPane>(
BrowserViewInFxml::class.java.getResource("browser-view.fxml")
)
primaryStage.title = "JavaFX BrowserView in FXML"
primaryStage.scene = Scene(pane, 1024.0, 600.0)
primaryStage.show()
}
}
fun main(args: Array<String>) {
Application.launch(BrowserViewInFxml::class.java, *args)
}
Once you run this example you should get the following output:
The complete example with all the classes and resources used in this section you can find in JxBrowser Examples.
SWT
To display the content of a web page in a Java SWT application create an instance of the com.teamdev.jxbrowser.view.swt.BrowserView
:
import com.teamdev.jxbrowser.view.swt.BrowserView;
...
Display display = new Display();
Shell shell = new Shell(display);
...
BrowserView view = BrowserView.newInstance(shell, browser);
import com.teamdev.jxbrowser.view.swt.BrowserView
...
val display = Display()
val shell = Shell(display)
...
val view = BrowserView.newInstance(shell, browser)
Here is the complete example:
import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.view.swt.BrowserView;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
/**
* The simplest application with the integrated browser component.
*
* <p>This example demonstrates:
*
* <ol>
* <li>Creating an instance of {@link Engine}.
* <li>Creating an instance of {@link Browser}.
* <li>Embedding the browser into SWT via {@link BrowserView}.
* <li>Loading the "https://html5test.teamdev.com" web site.
* </ol>
*/
public final class BrowserViewSwt {
public static void main(String[] args) {
// Creating and running Chromium engine.
Engine engine = Engine.newInstance(HARDWARE_ACCELERATED);
Browser browser = engine.newBrowser();
// Loading the required web page.
browser.navigation().loadUrl("https://html5test.teamdev.com");
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("JxBrowser SWT");
shell.setLayout(new FillLayout());
// Creating SWT component for rendering web content loaded
// in the Browser instance.
BrowserView view = BrowserView.newInstance(shell, browser);
view.setSize(800, 600);
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
// Closing the engine and releasing all allocated resources.
engine.close();
display.dispose();
}
}
import com.teamdev.jxbrowser.browser.Browser
import com.teamdev.jxbrowser.dsl.browser.navigation
import com.teamdev.jxbrowser.engine.Engine
import com.teamdev.jxbrowser.engine.RenderingMode
import com.teamdev.jxbrowser.view.swt.BrowserView
import org.eclipse.swt.layout.FillLayout
import org.eclipse.swt.widgets.Display
import org.eclipse.swt.widgets.Shell
/**
* The simplest application with the integrated browser component.
*
* This example demonstrates:
*
* 1. Creating an instance of [Engine].
* 2. Creating an instance of [Browser].
* 3. Embedding the browser into SWT via [BrowserView].
* 4. Loading the "https://html5test.teamdev.com" website.
*/
fun main() {
// Creating and running Chromium engine.
val engine = Engine.newInstance(RenderingMode.HARDWARE_ACCELERATED)
val browser = engine.newBrowser()
// Loading the required web page.
browser.navigation.loadUrl("https://html5test.teamdev.com")
val display = Display()
val shell = Shell(display)
shell.text = "JxBrowser SWT"
shell.layout = FillLayout()
// Creating an SWT component for rendering web content loaded
// in the Browser instance.
val view = BrowserView.newInstance(shell, browser)
view.setSize(800, 600)
shell.pack()
shell.open()
while (!shell.isDisposed) {
if (!display.readAndDispatch()) {
display.sleep()
}
}
// Closing the engine and releasing all allocated resources.
engine.close()
display.dispose()
}
The output of this example looks as follows:
See also our video tutorial that shows how to add BrowserView
to a Java SWT application:
Compose Desktop
To display the content of a web page in a Compose Desktop application, use the com.teamdev.jxbrowser.view.compose.BrowserView
composable:
import com.teamdev.jxbrowser.view.compose.BrowserView
...
BrowserView(browser)
Currently, this composable only supports the off-screen rendering mode.
Here is the complete example:
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.singleWindowApplication
import com.teamdev.jxbrowser.browser.Browser
import com.teamdev.jxbrowser.dsl.Engine
import com.teamdev.jxbrowser.dsl.browser.navigation
import com.teamdev.jxbrowser.engine.Engine
import com.teamdev.jxbrowser.engine.RenderingMode
import com.teamdev.jxbrowser.view.compose.BrowserView
/**
* The simplest application with the integrated browser component.
*
* This example demonstrates:
*
* 1. Creating an instance of [Engine].
* 2. Creating an instance of [Browser].
* 3. Embedding the browser into Compose Desktop via [BrowserView].
* 4. Loading the "https://html5test.teamdev.com" website.
*/
fun main() {
// Creating and running Chromium engine.
val engine = Engine(RenderingMode.OFF_SCREEN)
val browser = engine.newBrowser()
// Loading the required web page.
browser.navigation.loadUrl("https://html5test.teamdev.com")
singleWindowApplication(
title = "Compose Desktop BrowserView",
state = WindowState(width = 800.dp, height = 600.dp),
) {
// Creating a Compose component for rendering web content
// loaded in the given Browser instance.
BrowserView(browser)
DisposableEffect(Unit) {
onDispose {
// Close the engine when the app window leaves the composition.
engine.close()
}
}
}
}
The output of this example looks as follows:
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 Chromium renders the produced pixels.
Performance
The rendering performance is the same as in Chromium or Google Chrome due to the fact that Chromium renders the pixels directly on a native window embedded into the BrowserView
component. An average rendering performance in Frame Per Second (FPS) of an HTML5 video is ~60FPS.
Limitations
In Swing application, please avoid embedding Swing BrowserView into JInternalFrame
or JLayeredPane
, or display other Swing components over BrowserView
. In this rendering mode JxBrowser embeds and displays a native heavyweight window. Displaying a heavyweight window inside a lightweight Swing GUI 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.
In JavaFX application, configuring javafx.stage.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 you embed JavaFX BrowserView into a layered window, its content will not be painted because of the window types conflict.
In Eclipse RCP application on macOS, when the hardware accelerated rendering mode is enabled, SWT widgets might not be displayed on top of the SWT BrowserView, because it renders content using Layer-Backed NSView
when the other SWT widgets draw their content using regular NSView
. Content of a regular NSView
cannot overlap content of the Layer-Backed NSView
. It is because the rendering happens in the different drawing contexts and the regular NSView
will always be displayed under the Layer-Backed NSView
.
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
In the Off-Screen rendering mode the performance is different for each UI toolkit and operating system. The results of the rendering performance testing on an HTML5 video in FPS are the following:
Windows
- AMD Ryzen 9 3900X 12-Core 3.79GHz, 64GB RAM, GPU NVIDIA GeForce RTX 3080
- Video dimension: 1920x1080 (Full HD)
Compose |------------------------------------------------------------| 60FPS
JavaFX |------------------------------------------------------------| 60FPS
Swing |------------------------------------------------------------| 60FPS
SWT |------------------------------------------------------------| 60FPS
macOS
- MacBook Pro 16, M3 Max, 48GB RAM
- Video dimension: 3840x2160 (4K)
Compose |------------------------------------------------------------| 60FPS
JavaFX |------------------------------------------------------------| 60FPS
Swing |------------------------------------------------------------| 60FPS
SWT |------------------------------------------------------------| 60FPS
Linux
- AMD FX-8300 3.3 GHz with GPU Radeon RX 480
- Video dimension: 1920x1080 (Full HD)
Compose |----------------------------------------------| 46FPS
JavaFX |--------------------------------------------| 44FPS
Swing |----------------------------------------------------------| 58FPS
SWT |----------------| 16FPS
Limitations
In this rendering mode on Windows, Linux, and macOS (both rendering modes), the mouse, keyboard, and touch events are processed on the Java side and forwarded to Chromium. Java Swing, JavaFX, SWT, and Compose UI toolkits do not provide a fully functional touch events support, so JxBrowser does not support some touch gestures.
The same limitation applies to the Drag and Drop (DnD) functionality. DnD is processed using the Java DnD 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 Swing, JavaFX, and SWT BrowserView
. To disable drag and drop use the following way:
browserView.dragAndDrop().disable();
browserView.dragAndDrop().disable()
HiDPI
This section describes capabilities and limitations of JxBrowser in the environments with HiDPI displays.
macOS
On macOS, JxBrowser supports HiDPI and Retina displays out of the box in Swing, JavaFX, and SWT.
Windows
On Windows, JxBrowser supports HiDPI displays out of the box in Swing and JavaFX.
SWT
The library only recognizes the scale factor of a primary monitor. The scale factor must be a multiple of 25%. It is mandatory to use the swt.autoScale
system property if you need HiDPI support. The supported values are quarter
and exact
:
java -Dswt.autoScale=quarter -jar application.jar
In Eclipse 4.6 and higher, the swt.autoScale
property is always quarter
.
You can read more about swt.autoScale
here.
Linux
The scale factor should be explicitly configured when launching JVM. It is automatically detected.
Swing
To configure the scale factor in a Swing application, use the sun.java2d.uiScale
system property.
It accepts only integer values.
java -Dsun.java2d.uiScale=2 -jar application.jar
JavaFX
To configure the scale factor in a JavaFX application, use the glass.gtk.uiScale
system property.
It accepts only integer values.
java -Dglass.gtk.uiScale=2 -jar application.jar