【发布时间】:2015-11-11 22:49:57
【问题描述】:
Swing 通常会组合多个 repaint() 请求,以便只驱动一次 paintComponent() 方法,从而提高性能。通常,这就是您想要的。
但是,在我的应用程序中,这是不可取的。我的组件是一个充满文本的大屏幕(如文本编辑器)。每个字符都包含前景色/背景色和样式(如粗体)等属性。重新绘制整个屏幕(repaint(() 默认执行)是一项昂贵的操作,并且在仅更新屏幕上的几个不同字符时会引入不必要的延迟。
因此,我多次调用 repaint(x, y, width, height) ,但只针对那些实际发生变化的区域(通常为 50 个字符或更少,可能会分散在屏幕上两三个单独的区域,连续区域)。
问题是,通常我会在屏幕的顶部和底部更改字符。我为每个受影响的区域调用重绘,但是 Swing 通过计算要重绘的区域的联合,将我的多个 repaint(...) 请求组合成一个 repaint(...) 请求(这是默认行为)。这将导致对paintComponent() 的单个调用,但带有一个包含所有要更新的区域的大剪切矩形(由getClipBounds() 返回)。因此,无论如何(基于 ClipBounds),我最终都会重新绘制屏幕的大部分区域,这会适得其反,我希望避免这种情况,因为实际上只有一小部分屏幕被修改过,因此需要重新粉刷。
问题:有什么办法可以缓解这种行为,让我的 paintComponent() 方法只重绘那些已修改的区域,并避免对未修改区域进行不必要的重绘?
根据要求提供更多详细信息:
该类是从 JComponent 派生的。基本上,它只是一个“空”窗口,我使用 Swing 的 API 在其上绘制文本字符。窗口的最大尺寸约为 83 行 x 每行 320 列(这是在 Apple Cinema 显示器上),因此对于 8x16 字体,即为 2560x1328。
基本上,该应用程序是一个文本编辑器(想想:vi)。显示屏的底线是状态行。在最坏的情况下,我可能会将光标移动到窗口顶部右侧的一个位置。这将导致窗口底部的状态行被更新以反映新的光标位置(行、列)。因此,我们在窗口顶部有一些位置发生变化,在窗口底部有一些位置发生变化。我会发出 2 个 repaint(...) 请求,一个用于窗口的每个修改区域。但是,repaint() 将结合这两个请求,并使用边界矩形(定义要重新绘制的区域)调用一次 paintComponent(),该边界矩形是实际更新的两个区域的 union。生成的矩形将非常大,从窗口顶部延伸到底部。因此,在paintComponent() 中,我最终重新绘制了屏幕的很大一部分,即使大部分都没有被修改。这就是我要避免的。
【问题讨论】:
-
您是否考虑过使用文本组件(如
JTextPane或JEditorPane)来代替? -
您能提供更多信息吗?正在重新绘制什么样的组件?
标签: java swing paintcomponent repaint