You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swing中paintComponent的drawString性能异常及缓冲图像影响问题

Swing中drawString性能异常现象的原因分析

测试现象回顾

  • 在paintComponent方法中调用fillRect(100,100,100,100),执行耗时0ms,性能极佳
  • 将代码替换为drawString("hello",100,100)后,首次调用耗时140-160ms,且paintComponent方法会执行两次,第二次耗时0ms
  • 在构造函数中创建BufferedImage并调用其Graphics的drawString后,即使paintComponent中未使用该缓冲,其中的drawString("hello",300,300)耗时又变为0ms;移除构造函数中的drawString代码后,性能再次变差

核心原因解析

  1. 字体渲染上下文的首次初始化开销
    Swing的drawString依赖Java2D底层的字体渲染引擎,第一次调用时需要完成一系列高开销的初始化操作:加载对应字体文件、解析字体字形数据、创建FontRenderContext渲染上下文、初始化字体缓存结构等。这些操作是一次性的,但首次执行耗时明显。而fillRect是基础图形绘制,不需要涉及字体相关的初始化流程,因此耗时几乎为0。

  2. Swing重绘机制的二次触发
    第一次调用drawString时,字体初始化的延迟导致组件渲染未在预期时间内完成,Swing的重绘检测机制会判定组件内容未完全渲染,进而自动触发第二次重绘(即paintComponent执行两次)。第二次调用时,字体渲染上下文已经初始化完成,drawString直接复用已有的缓存数据,因此耗时骤降为0。

  3. 提前初始化共享字体缓存的作用
    在构造函数中通过BufferedImage的Graphics调用drawString,本质是提前触发了字体渲染上下文的初始化——Java2D的字体缓存是上下文共享的,即使这个缓冲图像未被实际使用,后续paintComponent中的drawString也能直接复用已经初始化好的字体数据和渲染上下文,因此不再产生首次初始化的开销,耗时回归0ms。移除这段初始化代码后,首次调用drawString又需要重新执行初始化流程,性能自然再次下降。

内容的提问来源于stack exchange,提问作者Spektra Lami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:23:10