2015-11-11 27 views
0

Swing通常会组合多个repaint()请求,以便只驱动paintComponent()方法一次,从而提高性能。通常情况下,这是你想要的。如何避免Swing结合repaint()请求?

但是在我的应用程序中,这是不可取的。我的组件是一个充满文本的大屏幕(如文本编辑器)。每个字符都包含前景/背景颜色和样式等属性(如BOLD)。重绘整个屏幕(默认情况下重绘(())是一项昂贵的操作,并且在屏幕上仅更新几个不同字符时引入不必要的延迟。 ,高度)多次,但只适用于实际发生变化的区域(通常为50个字符或更少,可能分散在两个或三个独立的连续区域的屏幕上)。

问题是,在屏幕的顶部和底部会有字符变化,我为每个受影响的区域调用repaint,但Swing将我的多个repaint(...)请求合并为一个repaint(...)请求(这是默认行为)通过计算要重新绘制的区域的联合,这导致一次调用paintComponent(),但带有一个大的剪切矩形(由getClipBounds()返回),它包含所有要更新的区域。因此,无论如何(基于ClipBounds),我都会重新粉刷大面积的屏幕,这会产生不利影响,我希望避免这种情况,因为屏幕的一小部分实际上已被修改,因此需要粉刷一新。

问题:有什么办法可以减轻这种行为,这样我的paintComponent()方法只重绘那些已被修改的区域,并避免不必要地重绘未修改的区域?

的额外细节,如请求:

的类是从衍生的JComponent。基本上,这只是一个“空白”窗口,我使用Swing的API绘制文本字符。窗口的最大尺寸大约为83行×320列(这是在Apple Cinema显示屏上),所以对于8x16字体,这是2560x1328。

基本上,应用程序是一个文本编辑器(想想:vi)。显示屏的最后一行是状态行。在最坏的情况下,我可能会将光标移到窗口顶部的右边一个位置。这会导致窗口底部的状态行被更新以反映新的光标位置(行,列)。所以,我们在窗口顶部有几个位置发生变化,并且窗口底部有一些位置发生变化。我将发出2个重绘(...)请求,每个修改窗口的区域一个。然而,repaint()会合并这两个请求,并用一个边界矩形(定义要重新绘制的区域)调用paintComponent(),这个边界是实际更新的两个区域的union。由此产生的矩形将非常大,从窗口顶部延伸到底部。因此,在paintComponent()中,我重新绘制了大部分屏幕,甚至认为绝大部分屏幕没有被修改。这正是我想要避免的。

+1

您是否考虑过使用文本组件(如'JTextPane'或'JEditorPane')? – MadProgrammer

+1

你能提供更多信息吗?什么样的组件正在重新绘制? – mascoj

回答

0

有什么办法来缓解这种行为,让自己的paintComponent()方法重绘只有那些被修改的区域,

你可以尝试使用JComponent类的paintImmediately(...)方法。

这将导致多个较小的绘画请求立即完成,而没有RepaintManager的好处。只有您可以决定是否有多个较小的请求比单个较大的绘制请求执行得更好。

+0

AFAIK必须从EDT中调出 – mKorbel

+0

是的,paintImmediately(...)似乎解决了我的问题,因为它基本上在paintImmediately(...)调用范围内驱动paintComponent(...)。不是一个摇摆爱好者,我忽略了这一点,你的第一个提到它我见过。正如mKorbel指出的,这一切都必须在美国东部时间下进行,这是我的代码符合的先决条件。我应该指出重绘(...)通常是更新GUI的“正确”方法,但就我而言,出于上述原因,重绘(...)效果不佳,而paintImmediately(..) )达到了预期的目标。谢谢! – BluesBrother