Java Swing中的revalidate()与repaint()的区别

231

我正在开发一个 Swing 应用程序,经常需要替换 JPanel 的内容。为此,我调用 removeAll() 方法,然后添加新的内容,最后调用 revalidate() 方法。

但是我发现旧内容仍然可见(被新内容遮挡)。如果我同时调用 repaint()revalidate() 方法,则可以按预期工作。

我确定在其他情况下只需要调用 revalidate() 方法就足够了。

所以我的问题基本上是,我是否需要同时调用这两个函数,如果不需要,应该在什么时候调用它们?


8
这个来自Oracle的教程指出:"在重新验证之后,始终调用repaint"。然而,并没有提供任何解释。 - mins
5个回答

176
你需要调用repaint()revalidate()。 第一个告诉Swing窗口中的某个区域已经变脏(这对于擦除removeAll()删除的旧子对象的图像是必要的);第二个告诉布局管理器重新计算布局(当添加组件时是必要的)。这应该导致此面板的子元素重新绘制,但可能不会导致面板本身这样做(请参见获取刷新触发器列表)。
更一般地说:与其重用原始面板,我建议构建一个新面板并将它们与父级交换。

3
你能否说明为什么建造一个新的面板比使用旧的更好呢? :) - Arttu
5
@Arttu - 这会减少工作量,因此减少出错的可能性。 - kdgregory

91
任何时候你使用remove()或removeAll()方法,都应该调用
  validate();
  repaint();

在完成添加新的组件后,必须调用validate()或revalidate()函数。这是因为当你使用remove()时需要查看相关的Java文档。

经过我的测试显示,repaint()也是必要的,但我不确定原因。


63

revalidate在添加新组件或移除旧组件后会被调用。这个调用是一个指令,告诉布局管理器基于新的组件列表进行重置。 revalidate将触发对组件认为是“脏区域”的重绘调用 。显然,并非您的JPanel上的所有区域都被RepaintManager视为脏区域。

repaint用于让组件重新绘制自己。经常需要调用它来清理类似您的情况。


7

revalidate() 方法会请求重新布局容器,当你遇到需要简单地调用 revalidate() 方法时,可能是由于子组件的更新触发了 repaint() 方法,在重新布局期间改变它们的边界。在你提到的情况中,只有组件被移除而没有组件边界被更改,这种情况下不会“意外”触发 repaint() 方法。


-4

是的,当你调用 removeAll() 方法时,你需要调用 repaint() 和 revalidate() 方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接