List icon 目录

渲染

本指南将说明不同渲染模式的工作机制,并探讨其限制。

概述 

JxBrowser 在 BrowserView中渲染网页内容的方式由渲染模式决定。JxBrowser 提供两种渲染模式:HARDWARE_ACCELERATED(硬件加速模式)和 OFF_SCREEN(离屏模式)。

渲染模式需在创建 Engine 实例时指定,且指定后无法更改。该 Engine 下创建的所有浏览器实例都将使用相同的渲染模式。

Java
Kotlin

import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;
...
var engine = Engine.newInstance(HARDWARE_ACCELERATED);

import com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED
...
val engine = Engine(HARDWARE_ACCELERATED)

选择合适的渲染模式会影响以下方面:

  • 渲染性能,
  • 整体资源占用,
  • JxBrowser 处理用户输入的方式。

当 GPU 可用时,Chromium 在两种渲染模式下都会使用硬件加速。当 GPU 不可用时,Chromium 会切换到 CPU 密集型软件渲染——同样在两种渲染模式下都会使用软件渲染。

硬件加速 

在该渲染模式下,Chromium 会将网页内容直接渲染到库放置在 BrowserView 上方的一个特殊渲染表面上。该表面的类型取决于操作系统。

Architecture of the HARDWARE_ACCELERATED rendering mode

HARDWARE_ACCELERATED 渲染模式的架构。

在 Windows 和 Linux 上,JxBrowser 会将一个原生的 Chromium 窗口嵌入 Java 应用中。通过这种方式,Chromium 会在它自己的窗口中渲染内容,其性能与独立浏览器相同。该嵌入式窗口对最终用户不可见:它没有 Chromium 的界面元素、任务栏图标,也没有普通窗口的特征。

No visual difference between the rendering modes

嵌入式窗口看起来与普通 UI 组件无异。

在 macOS 上,JxBrowser 会创建一个原生的 CARemoteLayer 表面,该表面在 Java 进程与 Chromium 进程之间共享。该表面被嵌入 Java 窗口,Chromium 会直接将内容渲染到这个表面上。

在 macOS 上需要采用不同的方式,因为操作系统只允许原生窗口在相同进程内重新归属(re-parent)。由于 JxBrowser 在独立进程中启动 Chromium,因此该 Chromium 窗口无法像 Windows 和 Linux 那样附加到 Java 窗口层级结构中。

输入处理 

在 Windows 和 Linux 上,输入事件由 Chromium 处理。由于用户直接与 Chromium 窗口交互,操作系统会将键盘、辅助功能以及其他输入事件直接发送给该窗口,绕过 Java 窗口。这确保了输入行为与 Google Chrome 完全一致。

在 macOS 上,输入事件由 Java UI 工具包处理。详情请参阅渲染模式中的“输入处理”部分。

你可以在 Java 代码中拦截鼠标、键盘和触摸事件。请参阅事件拦截指南了解具体方法。

限制 

与其他 UI 组件重叠 

无论操作系统如何,网页内容的渲染表面始终位于 Java 窗口之上。因此,普通 UI 组件无法显示在 BrowserView 上方,因为渲染表面积覆盖了该区域。

尤其要注意的是,在 Swing 中将 BrowserView 添加到 JInternalFrameJLayeredPane,或在 JavaFX 中将 StackPane 添加到 JLayeredPane 时,应避免使用 HARDWARE_ACCELERATED 渲染模式。

JxBrowser 与其他组件重叠

两个 BrowserView 组件(处于不同模式)与 JPanel 重叠。

JavaFX 中的透明窗口 

在 Windows 上的 JavaFX 中,HARDWARE_ACCELERATED 渲染模式与 StageStyle.TRANSPARENT 样式不兼容。为了显示透明的 Stage,JavaFX 使用分层窗口,但这种方法不适用于嵌入式 Chromium 窗口。

离屏 

在此渲染模式下,Chromium 仍通过 GPU 渲染内容。随后,库会将像素复制到 Java 进程内存中的离屏缓冲区BrowserView 在其中扮演轻量级组件的角色,通过标准 UI 工具包的图形功能(例如 Swing 中的 Graphics2D)从缓冲区读取像素并进行显示。

Architecture of the OFF_SCREEN rendering mode

OFF_SCREEN 渲染模式的架构。

输入处理 

默认情况下,输入事件由 Java 窗口处理。当发生输入事件时,操作系统会将其分派给 Java UI 工具包,该工具包会将其传递给 BrowserViewBrowserView 再将其转发给 Chromium,最终由 Chromium 将其传递给网页。

限制 

原生输入处理 

在事件处理的每个阶段,事件都会从一种数据结构转换为另一种数据结构。由于不同子系统中的数据结构并不完全匹配,数据可能会丢失或被错误解读。这会导致极少数情况下,用户在 JxBrowser 中的交互会生成与在 Chromium 中相同的交互不同的 JavaScript 事件。

在 JxBrowser 7.39.0 中,我们引入了一项实验性功能,该功能会将输入事件直接从操作系统转发到 Chromium。这样,JxBrowser 中生成的 JavaScript 事件将始终与 Chromium 中的事件保持一致。

要启用此功能,请使用系统属性:

System.setProperty("jxbrowser.native.input.enabled", "true");

触摸事件 

Swing、JavaFX、SWT 和 Compose 都缺乏完整的触摸支持。因此,某些 Chromium 手势(例如双指缩放)在 JxBrowser 中无法正常工作:在 Windows 和 Linux 的 OFF_SCREEN 模式,以及 macOS 的两种渲染模式中均如此。

性能 

HARDWARE_ACCELERATED 模式下,由于 Chromium 会直接在渲染表面绘制内容,GPU 的使用情况会直接影响渲染性能。该模式提供与独立版 Google Chrome 一致的渲染性能,在大多数平台上,可实现 4K 视频 60 帧 / 秒(FPS)的输出效果。

OFF_SCREEN 模式下,使用 GPU 能提升整体资源消耗表现,但对渲染性能提升不大。在该模式中,瓶颈在于进程间复制像素,这是一个依赖 CPU 的操作。在大多数情况下,此模式仍可提供良好的渲染性能。对于渲染性能至关重要的应用,推荐使用 HARDWARE_ACCELERATED 模式。

无头模式 

当不需要在用户界面中显示浏览器时,建议使用 HARDWARE_ACCELERATED 渲染模式。原因是,即使浏览器未显示,OFF_SCREEN 模式也可能消耗额外的 CPU 和内存。

无论使用哪种渲染模式,JxBrowser 在 BrowserView 之外都能正常工作。例如,您可以截取任意渲染模式下为独立的(未附加到视图的)Browser 进行截图

Java
Kotlin

var engine = Engine.newInstance(HARDWARE_ACCELERATED);
var browser = engine.newBrowser();

browser.resize(1920, 1080);
browser.navigation().loadUrlAndWait("https://html5test.teamdev.com");

// 截取网页位图,尺寸为 1920×1080
var bitmap = browser.bitmap();

import com.teamdev.jxbrowser.dsl.Engine
...
val engine = Engine(HARDWARE_ACCELERATED)
val browser = engine.newBrowser()

browser.resize(1920, 1080)
browser.navigation().loadUrlAndWait("https://html5test.teamdev.com")

// 截取网页位图,尺寸为 1920×1080
val bitmap = browser.bitmap()