渲染
本指南将说明不同渲染模式的工作机制,并探讨其限制。
概述
JxBrowser 在 BrowserView中渲染网页内容的方式由渲染模式决定。JxBrowser 提供两种渲染模式:HARDWARE_ACCELERATED(硬件加速模式)和 OFF_SCREEN(离屏模式)。
渲染模式需在创建 Engine 实例时指定,且指定后无法更改。该 Engine 下创建的所有浏览器实例都将使用相同的渲染模式。
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 上方的一个特殊渲染表面上。该表面的类型取决于操作系统。
HARDWARE_ACCELERATED 渲染模式的架构。
在 Windows 和 Linux 上,JxBrowser 会将一个原生的 Chromium 窗口嵌入 Java 应用中。通过这种方式,Chromium 会在它自己的窗口中渲染内容,其性能与独立浏览器相同。该嵌入式窗口对最终用户不可见:它没有 Chromium 的界面元素、任务栏图标,也没有普通窗口的特征。

嵌入式窗口看起来与普通 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 添加到 JInternalFrame 或 JLayeredPane,或在 JavaFX 中将 StackPane 添加到 JLayeredPane 时,应避免使用 HARDWARE_ACCELERATED 渲染模式。

两个 BrowserView 组件(处于不同模式)与 JPanel 重叠。
JavaFX 中的透明窗口
在 Windows 上的 JavaFX 中,HARDWARE_ACCELERATED 渲染模式与 StageStyle.TRANSPARENT 样式不兼容。为了显示透明的 Stage,JavaFX 使用分层窗口,但这种方法不适用于嵌入式 Chromium 窗口。
离屏
在此渲染模式下,Chromium 仍通过 GPU 渲染内容。随后,库会将像素复制到 Java 进程内存中的离屏缓冲区。BrowserView 在其中扮演轻量级组件的角色,通过标准 UI 工具包的图形功能(例如 Swing 中的 Graphics2D)从缓冲区读取像素并进行显示。
OFF_SCREEN 渲染模式的架构。
输入处理
默认情况下,输入事件由 Java 窗口处理。当发生输入事件时,操作系统会将其分派给 Java UI 工具包,该工具包会将其传递给 BrowserView,BrowserView 再将其转发给 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 进行截图:
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()