List icon 目录

BrowserView

该文档描述了如何在 Swing、JavaFX、SWT 和 Compose Desktop 应用程序中嵌入显示网页内容的可视化组件。

概述

JxBrowser 可用于使用以下 Java GUI 框架构建的 Java 应用程序:

  • Swing
  • JavaFX
  • Compose Desktop
  • SWT

Browser 组件本身不是一个允许显示网页的可视化组件。要显示在 Browser 中加载的网页内容,请根据您使用的 GUI 框架,使用以下控件之一:

  • 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

要在 Java Swing 应用程序中显示网页内容,请创建一个 com.teamdev.jxbrowser.view.swing.BrowserView 的实例:

Java
Kotlin

var view = BrowserView.newInstance(browser);

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

并将其嵌入到 JFrame 中:

Java
Kotlin

frame.add(view, BorderLayout.CENTER);

frame.add(view, BorderLayout.CENTER)

这是完整的示例:

Java
Kotlin


import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
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.WindowConstants;

import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
import static javax.swing.SwingUtilities.invokeLater;

/**
 * 带有集成 Browser 组件的最简单应用程序。
 * <p>此示例演示了:
 *
 * <ol>
 *     <li>创建一个 {@link Engine} 实例。
 *     <li>创建一个 {@link Browser} 实例。
 *     <li>通过 {@link BrowserView} 将 Browser 嵌入到 Swing 中。
 *     <li>加载 "https://html5test.teamdev.com" 网站。
 * </ol>
 */
public final class BrowserViewSwing {
    public static void main(String[] args) {
        // 创建和运行 Chromium Engine。
        var engine = Engine.newInstance(HARDWARE_ACCELERATED);

        var browser = engine.newBrowser();
        // 加载所需的网页。
        browser.navigation().loadUrl("https://html5test.teamdev.com");

        invokeLater(() -> {
            // 创建一个 Swing 组件,
            // 用于渲染在给定 Browser 实例中加载的网页内容。
            var view = BrowserView.newInstance(browser);

            // 创建并显示 Swing 应用程序 Frame。
            var frame = new JFrame("JxBrowser AWT/Swing");
            // 在该应用程序 Frame 即将关闭时关闭其 Engine。
            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

/**
 * 带有集成 Browser 组件的最简单应用程序。
 *
 * 此示例演示了:
 *
 *  1. 创建一个 [Engine] 实例。
 *  2. 创建一个 [Browser] 实例。
 *  3. 通过 [BrowserView] 将 Browser 嵌入到 Swing 中。
 *  4. 加载 "https://html5test.teamdev.com" 网站。
 */
fun main() {
    // 创建和运行 Chromium Engine。
    val engine = Engine(RenderingMode.HARDWARE_ACCELERATED)
    val browser = engine.newBrowser()
    // 加载所需的网页。
    browser.navigation.loadUrl("https://html5test.teamdev.com")
    SwingUtilities.invokeLater {
        // 创建一个 Swing 组件,
        // 用于渲染在给定 Browser 实例中加载的网页内容。
        val view = BrowserView.newInstance(browser)

        // 创建并显示 Swing 应用程序 Frame。
        val frame = JFrame("JxBrowser AWT/Swing")
        // 在该应用程序 Frame 即将关闭时关闭其 Engine。
        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
    }
}

此示例的输出如下所示: AWT/Swing BrowserView

另请参阅我们的视频教程,其中展示了如何将 BrowserView 添加到 Java Swing 应用程序:

JavaFX

要在 JavaFX 应用程序中显示网页内容,请创建一个 com.teamdev.jxbrowser.view.javafx.BrowserView 的实例:

Java
Kotlin

var view = BrowserView.newInstance(browser);

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

并将其嵌入到 Scene 中:

Java
Kotlin

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

val scene = Scene(BorderPane(view), 800.0, 600.0)

这是完整的示例:

Java
Kotlin


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;

/**
 * 带有集成 Browser 组件的最简单应用程序。
 *
 * <p>此示例演示了:
 * <ol>
 *     <li>创建一个 {@link Engine} 实例。
 *     <li>创建一个 {@link Browser} 实例。
 *     <li>通过 {@link BrowserView} 将 Browser 嵌入到 JavaFX 中。
 *     <li>加载 "https://html5test.teamdev.com" 网站。
 * </ol>
 */
public final class BrowserViewJavaFx extends Application {

    @Override
    public void start(Stage primaryStage) {
        // 创建和运行 Chromium Engine。
        var engine = Engine.newInstance(HARDWARE_ACCELERATED);

        var browser = engine.newBrowser();
        // 加载所需的网页。
        browser.navigation().loadUrl("https://html5test.teamdev.com");

        // 创建一个 UI 组件,
        // 用于渲染给定 Browser 实例中加载的网页内容。
        var view = BrowserView.newInstance(browser);

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

        // 当该 stage 即将关闭时关闭其 Engine。
        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

/**
 * 带有集成 Browser 组件的最简单应用程序。
 *
 * 此示例演示了:
 *  1. 创建一个 [Engine] 实例。
 *  2. 创建一个 [Browser] 实例。
 *  3. 通过 [BrowserView] 将 Browser 嵌入到 JavaFX 中。
 *  4. 加载 "https://html5test.teamdev.com" 网站。
 */
class HelloWorld : Application() {
    override fun start(primaryStage: Stage) {
        // 创建和运行 Chromium Engine。
        val engine = Engine(RenderingMode.HARDWARE_ACCELERATED)
        val browser = engine.newBrowser()
        // 加载所需的网页。
        browser.navigation.loadUrl("https://html5test.teamdev.com")

        // 创建一个 UI 组件,
        // 用于渲染给定 Browser 实例中加载的网页内容。
        val view = BrowserView.newInstance(browser)
        val scene = Scene(BorderPane(view), 800.0, 600.0)
        primaryStage.title = "JxBrowser JavaFX"
        primaryStage.scene = scene
        primaryStage.show()

        // 当该 stage 即将关闭时关闭其 Engine。
        primaryStage.onCloseRequest = EventHandler { engine.close() }
    }
}

此示例的输出如下所示: JavaFX BrowserView

另请参阅我们的视频教程,其中展示了如何将 BrowserView 添加到 JavaFX 应用程序:

JFXPanel

我们建议您在 Swing 应用程序中使用 Swing BrowserView,在 JavaFX 应用程序中使用 JavaFX BrowserView

有时您可能需要将 JavaFX BrowserView 嵌入到 Swing 应用程序中。例如,如果您使用 JavaFX UI Toolkit 开发一个复杂的网页浏览器控件,并且您必须在 Swing/AWT 应用程序中显示此 JavaFX 控件。

从 7.1 版本开始,您可以通过 javafx.embed.swing.JFXPanel 将 JavaFX BrowserView 嵌入到 Swing/AWT 窗口中。它支持所有受支持的平台和所有渲染模式。

Java
Kotlin


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

import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
import static javafx.application.Platform.runLater;

/**
 * 这个示例演示了如何将 JavaFX 的 BrowserView 嵌入到
 * 显示在 Swing/AWT Frame 内的 JFXPanel 中。
 */
public final class JFXPanelExample {

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

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

        // 将 JFXPanel 嵌入到 Swing Frame 中。
        var fxPanel = new JFXPanel();
        frame.add(fxPanel, BorderLayout.CENTER);
        frame.setSize(600, 600);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 在 JavaFX UI 线程中初始化 JFXPanel。
        runLater(() -> initFX(fxPanel));
    }

    private static void initFX(JFXPanel fxPanel) {
        var engine = Engine.newInstance(HARDWARE_ACCELERATED);

        var browser = engine.newBrowser();
        browser.navigation().loadUrl("https://html5test.teamdev.com");
        // 创建 JavaFX BrowserView 并将其插入到 JFXPanel 中。
        var view = BrowserView.newInstance(browser);
        var 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

/**
 * 这个示例演示了如何将 JavaFX 的 BrowserView 嵌入到
 * 显示在 Swing/AWT Frame 内的 JFXPanel 中。
 */
fun main() = SwingUtilities.invokeLater {
    initAndShowGUI()
}

private fun initAndShowGUI() {
    val frame = JFrame("JFXPanel")

    // 将 JFXPanel 嵌入到 Swing Frame 中。
    val fxPanel = JFXPanel()
    frame.add(fxPanel, BorderLayout.CENTER)
    frame.setSize(600, 600)
    frame.isVisible = true
    frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE

    // 在 JavaFX UI 线程中初始化 JFXPanel。
    Platform.runLater {
        initFX(fxPanel)
    }
}

private fun initFX(fxPanel: JFXPanel) {
    val engine = Engine(RenderingMode.HARDWARE_ACCELERATED)
    val browser = engine.newBrowser()
    browser.navigation.loadUrl("https://html5test.teamdev.com")
    // 创建 JavaFX BrowserView 并将其插入到 JFXPanel 中。
    val view = BrowserView.newInstance(browser)
    val pane = BorderPane(view)
    fxPanel.scene = Scene(pane, 600.0, 600.0)
}

FXML

您可以使用下面这一节中描述的方法将 JavaFX BrowserView 嵌入到 FXML 应用程序中。

首先,请描述 browser-view.fxml 文件的结构,以告诉 JavaFX BrowserView 控件应该如何嵌入到 JavaFX 应用程序 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>

此 FXML 声明了一个由两个元素组成的组件:地址栏和 Browser View。地址栏代表一个简单的文本字段。在这里,我们可以键入一个 URL,然后按 Enter 键在下面的 Browser View 中加载它。Browser View 包含显示加载网页内容的 FxmlBrowserView

browser-view.fxml 文件中定义的 FxmlBrowserViewController 的实现如下所示:

Java
Kotlin


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;

/**
 * 表示一个包含地址栏和网页视图的 FXML 控制器,
 * 用于显示地址栏中的 URL 对应的内容。
 */
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 guides.zh.browserview.FxmlBrowserView
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

/**
 * 表示一个 FXML 控制器,该控制器包含地址栏和浏览器视图区域,
 * 用于显示地址栏中输入的 URL 对应的内容。
 */
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)
    }
}

您可能会注意到,控制器实现中使用了 FxmlBrowserView 而不是 JavaFX BrowserView。这是因为 JavaFX 的 BrowserView 没有提供默认的公共构造函数,因此无法直接在 FXML 中使用。要嵌入 JavaFX 的 BrowserView,请使用 FxmlBrowserView,它代表了一个简单的包装器,具有初始化和嵌入 JavaFX BrowserView 的默认公共构造函数。

FxmlBrowserView 类的实现如下所示:

Java
Kotlin


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;

/**
 * 一个用于 JavaFX {@link BrowserView} 的包装组件,
 * 允许在 FXML 应用程序中使用 BrowserView 实例。
 * 由于 JavaFX 的 BrowserView 没有提供默认的公共构造函数,
 * 因此无法直接在 FXML 中使用。
 */
public final class FxmlBrowserView extends StackPane {

    private final Browser browser;

    /**
     * 构造一个 {@code FxmlBrowserView} 的实例。
     */
    public FxmlBrowserView() {
        var engine = Engine.newInstance(RenderingMode.HARDWARE_ACCELERATED);
        browser = engine.newBrowser();
        var view = BrowserView.newInstance(browser);
        getChildren().add(view);
    }

    /**
     * 返回当前 Browser View 的 {@link Browser} 实例。
     */
    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

/**
 * 一个用于 JavaFX [BrowserView] 的包装组件,
 * 允许在 FXML 应用程序中使用 BrowserView 实例。
 * 由于 JavaFX 的 BrowserView 没有提供默认的公共构造函数,
 * 因此无法直接在 FXML 中使用。
 */
class FxmlBrowserView : StackPane() {

    private val browser: Browser

    /**
     * 构造一个 `FxmlBrowserView` 的实例。
     */
    init {
        val engine = Engine(RenderingMode.HARDWARE_ACCELERATED)
        browser = engine.newBrowser()
        val view = BrowserView.newInstance(browser)
        children.add(view)
    }

    /**
     * 返回当前 Browser View 的 [Browser] 实例。
     */
    fun browser() = browser
}

现在,我们已经具备了实施和运行 FXML 示例的一切条件:

Java
Kotlin

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

/**
 * 这个示例演示了如何通过 {@link com.teamdev.jxbrowser.view.javafx.FxmlBrowserView} 控件
 * 在 FXML 应用程序中使用 JavaFX 的 BrowserView。
 */
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 {
        var resource = BrowserViewInFxml.class.getResource("browser-view.fxml");
        if (resource == null) {
            throw new IllegalStateException("The browser-view.fxml file not found.");
        }
        BorderPane pane = FXMLLoader.load(resource);

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

import guides.pt.browserview.BrowserViewInFxml
import javafx.application.Application
import javafx.fxml.FXMLLoader
import javafx.scene.Scene
import javafx.scene.layout.BorderPane
import javafx.stage.Stage

/**
 * 这个示例演示了如何通过 [com.teamdev.jxbrowser.view.javafx.FxmlBrowserView] 控件
 * 在 FXML 应用程序中使用 JavaFX 的 BrowserView。
 */
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)
}

运行此示例后,您应该获得以下输出:

FXML Example Output

您可以在 JxBrowser 示例中找到包含本节中使用的所有类和资源的完整示例。

SWT

要在 Java SWT 应用程序中显示网页内容,请创建一个 com.teamdev.jxbrowser.view.swt.BrowserView 的实例:

Java
Kotlin

var display = new Display();
var shell = new Shell(display);
...
var 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)

这是完整的示例:

Java
Kotlin


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;

/**
 * 带有集成 Browser 组件的最简单应用程序。
 *
 * <p>此示例演示了:
 * <ol>
 *     <li>创建一个 {@link Engine} 实例。
 *     <li>创建一个 {@link Browser} 实例。
 *     <li>通过 {@link BrowserView} 将 Browser 嵌入到 SWT 中。
 *     <li>加载 "https://html5test.teamdev.com" 网站。
 * </ol>
 */
public final class BrowserViewSwt {

    public static void main(String[] args) {
        // 创建和运行 Chromium Engine。
        var engine = Engine.newInstance(HARDWARE_ACCELERATED);
        var browser = engine.newBrowser();

        // 加载所需的网页。
        browser.navigation().loadUrl("https://html5test.teamdev.com");

        var display = new Display();
        var shell = new Shell(display);
        shell.setText("JxBrowser SWT");
        shell.setLayout(new FillLayout());

        // 创建一个 SWT 组件,
        // 用于渲染加载在 Browser 实例中的网页内容。
        var view = BrowserView.newInstance(shell, browser);
        view.setSize(800, 600);

        shell.pack();
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }

        // 关闭 Engine 并释放所有已分配的资源。
        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

/**
 * 带有集成 Browser 组件的最简单应用程序。
 *
 * <p>此示例演示了:
 *  1. 创建一个 [Engine] 实例。
 *  2. 创建一个 [Browser] 实例。
 *  3. 通过 [BrowserView] 将 Browser 嵌入到 SWT 中。
 *  4. 加载 "https://html5test.teamdev.com" 网站。
 */
fun main() {
    // 创建和运行 Chromium Engine。
    val engine = Engine.newInstance(RenderingMode.HARDWARE_ACCELERATED)
    val browser = engine.newBrowser()

    // 加载所需的网页。
    browser.navigation.loadUrl("https://html5test.teamdev.com")

    val display = Display()
    val shell = Shell(display)
    shell.text = "JxBrowser SWT"
    shell.layout = FillLayout()

    // 创建一个 SWT 组件,
    // 用于渲染加载在 Browser 实例中的网页内容。
    val view = BrowserView.newInstance(shell, browser)
    view.setSize(800, 600)

    shell.pack()
    shell.open()

    while (!shell.isDisposed) {
        if (!display.readAndDispatch()) {
            display.sleep()
        }
    }

    // 关闭 Engine 并释放所有已分配的资源。
    engine.close()
    display.dispose()
}

此示例的输出如下所示: SWT BrowserView

另请参阅我们的视频教程,其中展示了如何将 BrowserView 添加到 Java SWT 应用程序:

Compose Desktop

要在 Compose Desktop 应用中显示网页内容,可以使用 com.teamdev.jxbrowser.view.compose.BrowserView 组合函数:

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
import com.teamdev.jxbrowser.view.swing.BrowserView


/**
 * 最简单的集成 Browser 组件的应用程序。
 *
 * 本示例演示了:
 *
 *  1. 创建 [Engine] 实例。
 *  2. 创建 [Browser] 实例。
 *  3. 通过 [BrowserView] 将 Browser 嵌入 Compose Desktop。
 *  4. 加载 "https://html5test.teamdev.com" 网站。
 */
fun main() {
    // 创建并运行 Chromium Engine。
    val engine = Engine(RenderingMode.OFF_SCREEN)
    val browser = engine.newBrowser()
    // 加载所需的网页。
    browser.navigation.loadUrl("https://html5test.teamdev.com")
    singleWindowApplication(
        title = "Compose Desktop BrowserView",
        state = WindowState(width = 800.dp, height = 600.dp),
    ) {
        // 创建一个 Compose 组件,
        // 用于渲染在指定 Browser 实例中加载的网页内容。
        BrowserView(browser)
        DisposableEffect(Unit) {
            onDispose {
                // 当应用窗口退出组合时关闭引擎。
                engine.close()
            }
        }
    }
}

目前,该组合函数仅支持离屏渲染模式。

以下是完整的示例:

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
import com.teamdev.jxbrowser.view.swing.BrowserView


/**
 * 最简单的集成 Browser 组件的应用程序。
 *
 * 本示例演示了:
 *
 *  1. 创建 [Engine] 实例。
 *  2. 创建 [Browser] 实例。
 *  3. 通过 [BrowserView] 将 Browser 嵌入 Compose Desktop。
 *  4. 加载 "https://html5test.teamdev.com" 网站。
 */
fun main() {
    // 创建并运行 Chromium Engine。
    val engine = Engine(RenderingMode.OFF_SCREEN)
    val browser = engine.newBrowser()
    // 加载所需的网页。
    browser.navigation.loadUrl("https://html5test.teamdev.com")
    singleWindowApplication(
        title = "Compose Desktop BrowserView",
        state = WindowState(width = 800.dp, height = 600.dp),
    ) {
        // 创建一个 Compose 组件,
        // 用于渲染在指定 Browser 实例中加载的网页内容。
        BrowserView(browser)
        DisposableEffect(Unit) {
            onDispose {
                // 当应用窗口退出组合时关闭引擎。
                engine.close()
            }
        }
    }
}

此示例的输出如下: Compose Desktop BrowserView

渲染

JxBrowser 支持多种渲染模式。在本节中,我们将描述每种模式及其性能及其限制,并根据 Java 应用程序的类型,为你提供选择正确模式的建议。

硬件加速

在这种渲染模式下,库使用 GPU 在 Chromium GPU 进程中渲染网页内容,并将其直接显示在表面上。在这种模式下,BrowserView 创建并嵌入了一个原生重量级窗口(表面),Chromium 在其上呈现生成的像素。

How the hardware accelerated rendering works

性能

由于 Chromium 直接在嵌入到 BrowserView 组件的本机窗口上渲染像素,因此渲染性能与 Chromium 或 Google Chrome 相同。HTML5 视频的*每秒帧数(FPS)*平均渲染性能约为 60FPS。

限制

在 Swing 应用程序中,请避免将 Swing BrowserView 嵌入到 JInternalFrameJLayeredPane 中,或在 BrowserView 上显示其他 Swing 组件。在此渲染模式下,JxBrowser 嵌入并显示本机重量级窗口。在轻量级 Swing GUI 中显示重量级窗口会导致一个著名的问题,即混合重量级和轻量级组件的问题。

根据该文章,混合重量级和轻量级组件的问题在 JDK 6 更新 12 和 JDK 7 构建 19 中已被修复。这仅适用于 Java Swing 重量级组件,如 java.awt.Canvas。JxBrowser 嵌入的是其自有的重量级原生小部件。因此,该修复在此情况下不适用。

在 JavaFX 应用程序中,使用 StageStyle.TRANSPARENT 样式配置 javafx.stage.Stage 会将 WS_EX_LAYERED 窗口样式标志添加到 Windows 上的 JavaFX 窗口。此标志用于创建分层窗口。分层窗口是一个在屏幕外绘制其内容的窗口。如果将 JavaFX BrowserView 嵌入到分层窗口中,其内容将不会被绘制,因为窗口类型发生了冲突。

在 macOS 的 Eclipse RCP 应用程序中,当启用硬件加速渲染模式时,SWT 小部件可能不会显示在 SWT BrowserView 之上,这是因为当其他 SWT 小部件使用常规 NSView 绘制其内容时,它使用 Layer-Backed NSView 渲染内容。常规 NSView 的内容无法覆盖 Layer-Backed NSView 的内容。这是因为渲染发生在不同的绘图上下文中,常规 NSView 总是显示在 Layer-Backed NSView 下。

离屏

在此渲染模式下,该库使用 Chromium GPU 进程通过 GPU 渲染网页内容,并将像素复制到分配在 Java 进程内存中的离屏缓冲区。在此模式下,BrowserView 创建并嵌入一个轻量级组件,该组件从离屏缓冲区读取像素,并使用标准 Java 图形 API 显示它们。

How the off-screen rendering works

性能

离屏渲染模式下,不同的 UI 工具包和操作系统的性能各不相同。针对 HTML5 视频的渲染性能测试结果(以 FPS 为单位)如下:

Windows

  • AMD Ryzen 9 3900X 12-Core 3.79GHz, 64GB RAM, GPU NVIDIA GeForce RTX 3080
  • 视频分辨率:1920x1080(全高清)
Compose |------------------------------------------------------------| 60FPS
 JavaFX |------------------------------------------------------------| 60FPS
  Swing |------------------------------------------------------------| 60FPS
    SWT |------------------------------------------------------------| 60FPS

macOS

  • MacBook Pro 16, M3 Max, 48GB RAM
  • 视频分辨率:3840x2160 (4K)
Compose |------------------------------------------------------------| 60FPS
 JavaFX |------------------------------------------------------------| 60FPS
  Swing |------------------------------------------------------------| 60FPS
    SWT |------------------------------------------------------------| 60FPS

Linux

  • AMD FX-8300 3.3 GHz with GPU Radeon RX 480
  • 视频分辨率:1920x1080(全高清)
Compose |----------------------------------------------| 46FPS
 JavaFX |--------------------------------------------| 44FPS
  Swing |----------------------------------------------------------| 58FPS
    SWT |----------------| 16FPS

限制

在此渲染模式下,Windows、Linux 和 macOS(两种渲染模式)中的鼠标、键盘和触控事件都在 Java 端处理并转发给 Chromium。Java Swing、JavaFX、SWT 和 Compose 等 UI 工具包不提供完全功能的触控事件支持,因此 JxBrowser 不支持某些触控手势。

同样的限制也适用于拖放(DnD)功能。DnD 使用 Java DnD API 进行处理,因此它的工作方式与 Google Chrome 并不完全相同。DnD 仅支持预定义的内容类型。

拖放

默认情况下,Swing、JavaFX 和 SWT BrowserView 启用拖放功能。要禁用拖放功能,请使用以下方式:

Java
Kotlin

browserView.dragAndDrop().disable();

browserView.dragAndDrop().disable()

HiDPI

本节介绍 JxBrowser 在具有 HiDPI 显示器的环境中的功能和限制。

macOS

在 macOS 上,JxBrowser 在 Swing、JavaFX 和 SWT 中默认支持 HiDPI 和 Retina 显示。

Windows

在 Windows 上,JxBrowser 在 Swing 和 JavaFX 中默认支持 HiDPI 显示。

SWT

在 SWT 3.127.0(Eclipse 2024-09)之前,该工具包仅能识别主显示器的缩放比例,且缩放比例必须为 25% 的倍数。如果需要 HiDPI 支持,必须使用 swt.autoScale 系统属性。支持的值为 quarterexact

java -Dswt.autoScale=quarter -jar application.jar

在 Eclipse 4.6 及更高版本中,swt.autoScale 属性始终设置为 quarter。 您可以在此处阅读有关 swt.autoScale 的更多信息。

从版本 3.127.0 开始,该工具包能够识别 Windows 上所有显示器的缩放比例,因此不应再使用此系统属性。

Linux

在 Linux 上,启动 JVM 时需要明确配置缩放因子。它会自动检测。

Swing

要在 Swing 应用程序中配置缩放因子,请使用 sun.java2d.uiScale 系统属性。它只接受整数值。

java -Dsun.java2d.uiScale=2 -jar application.jar

JavaFX

要在 JavaFX 应用程序中配置缩放因子,请使用 glass.gtk.uiScale 系统属性。它只接受整数值。

java -Dglass.gtk.uiScale=2 -jar application.jar