New version is available You are viewing the documentation for JxBrowser 6 which is not supported since December 2019. Go to the current documentation.
List icon Contents

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

Embedding

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

  • Swing
  • JavaFX
  • SWT

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

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

Swing

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

import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
 
import javax.swing.*;
import java.awt.*;
 
/**
 * This sample demonstrates how to create Browser instance,
 * embed it into Swing BrowserView container, display it in JFrame and
 * navigate to the "www.google.com" web site.
 */
public class BrowserSample {
    public static void main(String[] args) {
        Browser browser = new Browser();
        BrowserView browserView = new BrowserView(browser);
 
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(browserView, BorderLayout.CENTER);
        frame.setSize(700, 500);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
 
        browser.loadURL("http://www.google.com");
    }
}

On macOS, Chromium engine is initialized in Java process and it will not be uninitialized when last Browser instance is disposed. Chromium engine must be disposed manually after all Browser instances are disposed by using the BrowserCore.shutdown() method. This method is invoked asynchronously. Once you shutdown Chromium engine, you cannot use it anymore. Invoke this method only when Java application exits.

JavaFX

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

import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.BrowserCore;
import com.teamdev.jxbrowser.chromium.internal.Environment;
import com.teamdev.jxbrowser.chromium.javafx.BrowserView;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

/**
 * Demonstrates how to embed Browser instance into JavaFX application.
 */
public class JavaFXSample extends Application {

    @Override
    public void init() throws Exception {
        // On Mac OS X Chromium engine must be initialized in non-UI thread.
        if (Environment.isMac()) {
            BrowserCore.initialize();
        }
    }

    @Override
    public void start(final Stage primaryStage) {
        Browser browser = new Browser();
        BrowserView view = new BrowserView(browser);

        Scene scene = new Scene(new BorderPane(view), 700, 500);
        primaryStage.setScene(scene);
        primaryStage.show();

        browser.loadURL("http://www.google.com");
    }

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

In macOS environment you must initialize JxBrowser core functionality in non-UI thread. For example, in the Application.init() method as shown below:

@Override
public void init() throws Exception {
    // On Mac OS X Chromium engine must be initialized in non-UI thread.
    if (Environment.isMac()) {
        BrowserCore.initialize();
    }
}

FXML

It is possible to embed BrowserView into a JavaFX app GUI via FXML. In this section we will show you how to do it.

First we need to describe the structure of the browser-view-control.fxml file to tell JavaFX how the BrowserView control should be embedded into the app UI.

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

<?import com.teamdev.jxbrowser.chromium.javafx.BrowserView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane fx:controller="BrowserViewControl" xmlns:fx="http://javafx.com/fxml">
    <top>
        <TextField fx:id="textField" text="http://www.google.com" onAction="#loadURL"/>
    </top>
    <center>
        <BrowserView fx:id="browserView"/>
    </center>
</BorderPane>

Then we need to implement the BrowserViewControl defined in the browser-view-control.fxml file:

import com.teamdev.jxbrowser.chromium.javafx.BrowserView;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;

/**
 * Represents FXML control with address bar and view area that
 * displays URL entered in the address bar text field.
 */
public class BrowserViewControl implements Initializable {

    @FXML
    private TextField textField;

    @FXML
    private BrowserView browserView;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        browserView.getBrowser().loadURL(textField.getText());
    }

    public void loadURL(ActionEvent actionEvent) {
        browserView.getBrowser().loadURL(textField.getText());
    }
}

And finally, create an FXMLSample that displays the app GUI with the embedded BrowserView control using FXML:

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

/**
 * The sample demonstrates how to embed JavaFX BrowserView
 * component into JavaFX app using FXML.
 */
public class FXMLSample extends Application {

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

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

        primaryStage.setTitle("FXMLSample");
        primaryStage.setScene(new Scene(pane, 800, 600));
        primaryStage.show();
    }
}

SWT

JxBrowser supports Swing/AWT and JavaFX UI toolkits. It provides two implementations of the BrowserView class that can be used for embedding JxBrowser into Swing/AWT and JavaFX applications:

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

To embed JxBrowser into SWT applications you can use the approaches described below. These approaches are based on the third-party SWT-AWT and SWT-JavaFX components (bridges).

Mixing the two UI toolkits isn’t a simple task, so there might be some integration issues such as focus transferring, flickering, freezing, thread deadlocks, etc. You can read more about possible issues in the Swing/SWT Integration article.

On macOS Java should be run with -XstartOnFirstThread parameter in case you are not starting the script via Eclipse using macOS. Otherwise you will get the “org.eclipse.swt.SWTException: Invalid thread access” error. If you are using Eclipse, this parameter is applied automatically and you won’t encounter this error.

Since JxBrowser 6.0 we started initializing Chromium engine in Java process to enable heavyweight rendering mode. Chromium engine actively uses Cocoa UI threads as well as Java Swing, and SWT. It’s very important to initialize Chromium in Cocoa UI thread (AppKit). With using the -XstartOnFirstThread VM flag, default UI thread is changed to Java “main” thread which breaks Chromium functionality that requires AppKit thread. As result, Chromium fails to initialize in “main” thread and you see the freezing issue and later the “IPC cannot start because Chromium doesn’t respond” error message.

This is a regression issue caused by architectural changes in 6.0. It should be completely resolved after the implementation of SWT support.

Meanwhile, as a workaround, you can use lightweight rendering mode with the jxbrowser.ipc.external=true JVM parameter. In this case, Chromium engine will be initialized in a separate native process, so you will not see this issue anymore. Please note that with this JVM parameter you can use only lightweight browser mode.

Swing & SWT

To embed Swing/AWT implementation of com.teamdev.jxbrowser.chromium.swing.BrowserView into SWT application use the org.eclipse.swt.awt.SWT_AWT instance as shown below:

import java.awt.Frame;
 
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
 
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;
 
/**
 * The sample demonstrates how to use JxBrowser Swing control in 
 * SWT application using SWT_AWT bridge.
 */
public class JxBrowserSwingSWT {
    public static void main(String[] arguments) {
        Browser browser = new Browser();
        BrowserView view = new BrowserView(browser);
 
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
         
        Composite composite = new Composite(shell, 
                SWT.EMBEDDED | SWT.NO_BACKGROUND);
        Frame frame = SWT_AWT.new_Frame(composite);
        frame.add(view);
         
        browser.loadURL("http://google.com");
         
        shell.open();
         
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }
}

JavaFX & SWT

To embed JavaFX implementation of com.teamdev.jxbrowser.chromium.javafx.BrowserView into SWT application use the javafx.embed.swt.FXCanvas instance as shown below:

import javafx.embed.swt.FXCanvas;
import javafx.scene.Scene;
 
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
 
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.javafx.BrowserView;
 
/**
 * The sample demonstrates how to use JxBrowser JavaFX 
 * control in SWT application using FXCanvas.
 */
public class JxBrowserJavaFXSWT {
    public static void main(String[] arguments) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());
         
        Browser browser = new Browser();
        FXCanvas canvas = new FXCanvas(shell, SWT.NONE);
         
        // BrowserView instance must be initialized after FXCanvas.
        BrowserView view = new BrowserView(browser);
        canvas.setScene(new Scene(view));
         
        browser.loadURL("http://google.com");
         
        shell.open();
        while (!shell.isDisposed()) {
               if (!display.readAndDispatch()) {
                     display.sleep();
               }
        }
        display.dispose();
    }
}

Lightweight or Heavyweight

JxBrowser supports two rendering modes: lightweight and heavyweight.

By default, the heavyweight rendering mode is enabled, so when you create Browser instance using the following code, it creates a new Browser instance configured to use heavyweight rendering mode:

Browser browser = new Browser();

To create a new Browser instance with specified rendering mode use the following way:

// Creates Browser instance with enabled lightweight rendering mode
Browser browser = new Browser(BrowserType.LIGHTWEIGHT);

// Creates Browser instance with enabled heavyweight rendering mode
Browser browser = new Browser(BrowserType.HEAVYWEIGHT);

The differences between lightweight and heavyweight rendering modes and recommendations about what rendering mode you should use in your application you can find below.

Lightweight (off-screen)

In lightweight rendering mode Chromium engine renders web page off-screen using CPU. Images that represent different parts of loaded web page are stored in shared memory. JxBrowser reads the images from the shared memory and displays them using standard Java Swing/JavaFX 2D Graphics API.

To interact with displayed web page we listen to mouse and keyboard events using Java Events API, convert them to appropriate Chromium mouse/keyboard events, and send them to Chromium engine. With this approach we receive a pure lightweight solution.

This rendering mode works great if you need a true lightweight Swing/JavaFX component that allows displaying modern HTML5/JavaScript/CSS web pages in your Java application. You can make this lightweight component semitransparent, display other components on top of it, put it into JLayeredPane or JInternalFrame, get notifications about mouse and keyboard events, etc.

Please note, that JxBrowser does not support accessibility in a lightweight mode.

Headless environment

In case you need to use JxBrowser in a headless Linux environment, we recommend that you use the Lightweight rendering mode.

There are two main reasons for that:

  1. The Heavyweight (GPU-accelerated) rendering mode running in a headless environment via xvfb is useless because GPU acceleration in xvfb is disabled.
  2. Very often in such environment the JxBrowser functionality that allows getting screenshots of the loaded web-pages is used. That functionality is available in the Lightweight rendering mode only.

Lightweight Limitations

  • Heavy animation on loaded web page cause high CPU and memory usage. It happens because Chromium engine needs to render a lot of images and save them into allocated shared memory.
  • In lightweight mode only Chromium plugins that supports windowless mode can be displayed. Since rendering is done off-screen, Flash player or other plugin must support windowless (off-screen) rendering as well. If plugin doesn’t support off-screen rendering, it will not be displayed in lightweight mode.
  • Mouse/keyboard/touch events are processes on Java side and forwarded to Chromium engine. Right now Java doesn’t provide fully functional touch events support, so in lightweight rendering mode JxBrowser doesn’t support some touch gestures. Same limitation is true for Drag&Drop functionality. In lightweight rendering mode, drag and drop is processed using Java API, so it doesn’t work exactly as in Google Chrome. Drag&Drop supports only predefined set of flavours.

Accelerated Lightweight Rendering

In JxBrowser 6.10 and higher there’s an option that allows enabling accelerated lightweight rendering mode. This rendering mode has improved performance compared to default lightweight rendering mode. It allows producing ~30% more frames per second.

Accelerated lightweight rendering is faster than the ordinary lightweight rendering, as in the accelerated mode rendering is performed directly in RAM. The ordinary lightweight mode uses a video card where there is a phase of copying an image from video memory to RAM. As the stage of copying from video memory to RAM is absent in the accelerated lightweight mode, we can see an increase in speed.

The only disadvantage of this accelerated rendering mode is that it doesn’t support WebGL, because GPU process isn’t used in this case. If you don’t need to display web pages with WebGL, we recommend that you enable and use accelerated lightweight rendering mode.

To enable accelerated lightweight rendering mode you must specify the following Chromium switches before you create the first Browser instance in your application:

import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.BrowserPreferences;
import com.teamdev.jxbrowser.chromium.BrowserType;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;

import javax.swing.*;
import java.awt.*;

public class AcceleratedLightweightRenderingSample {
    public static void main(String[] args) {
        BrowserPreferences.setChromiumSwitches(
                "--disable-gpu",
                "--disable-gpu-compositing",
                "--enable-begin-frame-scheduling",
                "--software-rendering-fps=60"
        );

        Browser browser = new Browser(BrowserType.LIGHTWEIGHT);
        BrowserView view = new BrowserView(browser);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(view, BorderLayout.CENTER);
        frame.setSize(1100, 750);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        browser.loadURL("https://www.youtube.com/watch?v=lfwjzNB--5k");
    }
}

Heavyweight (GPU-accelerated)

In the heavyweight rendering mode, which is default mode in JxBrowser, we embed a native window into your Java application window and configure Chromium engine to render content into this native window using GPU.

User interaction with displayed web page is handled by the Chromium engine. The native Chromium window receives and processes all mouse/keyboard/touch events using platform specific native functionality when it is focused. Such behavior brings a better support of these events compared to the lightweight rendering mode where JxBrowser has to process Java events and forward them to Chromium engine.

However, when the native window is focused, the Java application does not receive the mouse/keyboard/touch events automatically, so these events are forwarded to the Java side after processing them in Chromium.

Heavyweight (GPU-accelerated) rendering mode works much faster compared to lightweight rendering mode. Rendering performance is the same as in Google Chrome. You can display full screen video or HTML5 animation with 60fps. Compared to lightweight rendering mode, CPU and memory usage is much smaller, because web page’s content is rendered via GPU.

So, if rendering performance is very important for your application, then we recommend that you use the default heavyweight rendering mode.

Heavyweight Limitations

Lightweight and heavyweight mixing

Java Swing/JavaFX toolkits allows building UI based on lightweight components. When we embed a native window into Java frame it can lead to a well-known issue with mixing heavyweight and lightweight components. It’s not recommended that you put heavyweight BrowserView component into JLayeredPane or JInternalFrame, or mix it with the lightweight components (e.g. trying to display a lightweight component over heavyweight BrowserView).

Layered windows in JavaFX applications

Configuring the stage with the StageStyle.TRANSPARENT style adds the WS_EX_LAYERED window style flag to JavaFX window. This flag is used to create a layered window. The layered window represents an off-screen window that draws its content off-screen. If we embed another window (it happens when heavyweight rendering mode is used in JxBrowser) into a layered window, its content will not be painted because of window types conflict.

Browser disposal in JavaFX

Disposing Browser instance in the incorrect thread in JavaFX may lead to a deadlock on the native side. The Browser instances must be disposed on different threads depending on the operating system. In Linux and macOS the Browser.dispose() method must be called on the UI thread, while on Windows Browser must be disposed on the non-UI thread. For example:

Linux and MacOS

Platform.runLater(new Runnable() {
    @Override
    public void run() {
        browser.dispose();
    }
});

Windows

new Thread(new Runnable() {
    @Override
    public void run() {
        browser.dispose();
    }
}).start();

Mouse and Keyboard

Handling Keyboard Events

Using the BrowserView.setKeyEventsHandler(InputEventsHandler<KeyEvent> handler) method you can decide what keyboard events should be suppressed before they will be sent to Chromium engine. The following example demonstrates how to disable the Ctrl+A shortcut for Swing BrowserView:

import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.InputEventsHandler;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;

/**
 * This sample demonstrates how to register key events handler to handle/suppress
 * Ctrl+A key events (e.g. to prevent text selection).
 */
public class KeyEventsHandlerSample {
    public static void main(String[] args) {
        Browser browser = new Browser();
        BrowserView view = new BrowserView(browser);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(view, BorderLayout.CENTER);
        frame.setSize(700, 500);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        view.setKeyEventsHandler(new InputEventsHandler<KeyEvent>() {
            public boolean handle(KeyEvent event) {
                return event.isControlDown() && event.getKeyCode() == KeyEvent.VK_A;
            }
        });

        browser.loadURL("http://www.google.com");
    }
}

Handling Mouse Events

Using the BrowserView.setMouseEventsHandler(InputEventsHandler<MouseEvent> handler) method you can decide what mouse events should be suppressed before they will be sent to Chromium engine. The following example demonstrates how to suppress mouse wheel events:

import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.InputEventsHandler;
import com.teamdev.jxbrowser.chromium.swing.BrowserView;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;

/**
 * This sample demonstrates how to register mouse events handler
 * to handle/suppress mouse wheel events.
 */
public class MouseEventsHandlerSample {
    public static void main(String[] args) {
        Browser browser = new Browser();
        BrowserView view = new BrowserView(browser);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(view, BorderLayout.CENTER);
        frame.setSize(700, 500);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        view.setMouseEventsHandler(new InputEventsHandler<MouseEvent>() {
            @Override
            public boolean handle(MouseEvent event) {
                return event.getID() == MouseEvent.MOUSE_WHEEL;
            }
        });

        browser.loadURL("http://www.google.com");
    }
}

Drag and Drop

Since 6.0 version JxBrowser supports two rendering modes: heavyweight (default mode) and lightweight. Drag and drop functionality is supported in both heavyweight and lightweight rendering modes, but for each rendering mode it works differently.

Lightweight Rendering Mode

In the lightweight rendering mode Drag and Drop functionality is implemented using Java Swing and JavaFX Drag&Drop API. Drag and Drop support is limited. It supports only the following features:

  • Drag selected text and links on loaded web page and drop them into other applications.
  • Drag selected text and links on loaded web page and drop them into text fields or text areas on the same web page.
  • Drag text from other applications and drop it into text fields or text areas on loaded web page.

Heavyweight Rendering Mode

In the heavyweight rendering mode Drag and Drop functionality is implemented by Chromium engine. Chromium handles all Drag and Drop operations, so it works exactly as in Google Chromium.

Disabling Drag and Drop

By default Drag and Drop is enabled. To disable Drag and Drop use the BrowserView.setDragAndDropEnabled(boolean enabled) method or the jxbrowser.chromium.dnd.enabled=false System Property.

In order to disable DnD in JavaFX, use the following approach:

import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.BrowserCore;
import com.teamdev.jxbrowser.chromium.BrowserType;
import com.teamdev.jxbrowser.chromium.internal.Environment;
import com.teamdev.jxbrowser.chromium.javafx.BrowserView;
import com.teamdev.jxbrowser.chromium.javafx.internal.LightWeightWidget;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

/**
 * The sample demonstrates how to disable functionality that allows dragging
 * links from the loaded web page.
 */
public class JavaFXDisableDnDSample extends Application {

    @Override
    public void init() throws Exception {
        // On Mac OS X Chromium engine must be initialized in non-UI thread.
        if (Environment.isMac()) {
            BrowserCore.initialize();
        }
    }

    @Override
    public void start(final Stage primaryStage) {
        Browser browser = new Browser(BrowserType.LIGHTWEIGHT);
        final BrowserView view = new BrowserView(browser);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                LightWeightWidget lightWeightWidget = (LightWeightWidget)
                        view.getChildren().get(0);
                if (lightWeightWidget.isDragAndDropEnabled()) {
                    // Now you cannot drag and drop links from the loaded web page.
                    lightWeightWidget.setDragAndDropEnabled(false);
                }
            }
        });

        Scene scene = new Scene(new BorderPane(view), 700, 500);
        primaryStage.setScene(scene);
        primaryStage.show();

        browser.loadURL("http://www.google.com");
    }

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

Transparent Background

In JxBrowser 6.10 and higher, there’s functionality that allows enabling support of transparent background on the web pages. The following example demonstrates how to enable support of transparent background:

BrowserPreferences preferences = browser.getPreferences();
preferences.setTransparentBackground(true);
browser.setPreferences(preferences);

Context Menu

By default JxBrowser doesn’t display context menu when user right clicks on the loaded web page. Standard Chromium context menu isn’t supported either because it’s part of Google Chromium application.

To display context menu when user right clicks on the loaded web page, you must register your ContextMenuHandler implementation. When user right clicks on the web page the ContextMenuHandler.showContextMenu(ContextMenuParams params) method is invoked. This method receives ContextMenuParams parameter that contains information about HTML element at mouse right click location on the web page, location of mouse pointer, type of HTML element under mouse pointer, link URL, link text, image src attribute value, etc. Use this information to configure context menu.

To register your implementation of the ContextMenuHandler use the Browser.setContextMenuHandler(ContextMenuHandler contextMenuHandler) method.

browser.setContextMenuHandler(new MyContextMenuHandler(view));
...
private static class MyContextMenuHandler implements ContextMenuHandler {

    private final JComponent component;

    private MyContextMenuHandler(JComponent parentComponent) {
        this.component = parentComponent;
    }

    public void showContextMenu(final ContextMenuParams params) {
        final JPopupMenu popupMenu = new JPopupMenu();
        if (!params.getLinkText().isEmpty()) {
            popupMenu.add(createMenuItem("Open link in new window", new Runnable() {
                public void run() {
                    String linkURL = params.getLinkURL();
                    System.out.println("linkURL = " + linkURL);
                }
            }));
        }

        final Browser browser = params.getBrowser();
        popupMenu.add(createMenuItem("Reload", new Runnable() {
            public void run() {
                browser.reload();
            }
        }));

        final Point location = params.getLocation();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                popupMenu.show(component, location.x, location.y);
            }
        });
    }

    private static JMenuItem createMenuItem(String title, final Runnable action) {
        JMenuItem reloadMenuItem = new JMenuItem(title);
        reloadMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                action.run();
            }
        });
        return reloadMenuItem;
    }
}

Shortcuts

In Chromium, there are two types of shortcuts. The shortcuts that are supported by the Chromium application and shortcuts that are supported by the Blink engine. JxBrowser supports only the second type of shortcuts because it does not integrate the Chromium application UI.

For example, JxBrowser supports shortcuts related to the editor like Ctrl+A/⌘+A, Ctrl+C/⌘+C, and Ctrl+X/⌘+X. JxBrowser does not support Ctrl+P/⌘+P and Ctrl+F/⌘+F shortcuts as they are provided by the Chromium application UI.

If you need to process an unsupported shortcut such as Ctrl+P/⌘+P, you can do it manually by registering the input listener like in the following sample:

browserView.setKeyEventsHandler(new InputEventsHandler<KeyEvent>() {
    public boolean handle(KeyEvent event) {
        if (event.isControlDown() && event.getKeyCode() == KeyEvent.VK_P
                && event.getID() == KEY_RELEASED) {
            browser.print();
        }
        return false;
    }
});