谁在调用paintComponent方法?

4
由于某种原因,我的paintComponent(Graphics g)方法被无限调用。即使在调用中转储了StackTrace(它是一个分派和处理的事件),我也无法确定是谁在调用它。
有没有简单的方法可以找出是谁触发了该事件?
更新:我已经找到了原因并理解了原因。回答正确的人将得到问题的答案。
这是导致问题的代码:
@Override
public void paintComponent(Graphics g)
{
    myJButton.setIcon(ResourceLoader.getImageIconWithLocale(MY_BUTTON_IMAGE));
    super.paintComponent(g);
}

注意: 这是一个非常棘手的问题!仅从代码上看并不明显。我做出了错误的假设。


你有样例代码可以分享吗? - Kushal Paudyal
1
如果代码被称为“无限”,那么你的代码中肯定有一个循环导致了问题。Swing 只会在需要时重新绘制组件。如果需要更多帮助,请发布演示问题的 SSCCE(http://sscce.org)。 - camickr
@camickr:我刚刚加了一些源代码,因为我发现了这个问题。 - Stephane Grenier
4个回答

2

我不知道这是哪个组件,但在绘制过程中设置按钮图标是一个不好的想法。它肯定会导致按钮被重绘。如果该按钮是您组件的子级,则设置按钮将使组件无效,从而导致无限循环。

将图标设置在其他地方,例如在对话框/窗口最初设置时。


接近了!你非常接近了。这不会导致它被重新绘制。 - Stephane Grenier

2

只有当ImageIcon是另一个实例时,才会使用setIcon(ImageIcon)重新验证和重绘自身。

在处理语言环境时,大多数人都习惯于使用ResourceBundle,它返回不可变的字符串。因此,反复设置文本并不重要。

然而,在这种情况下,ResourceLoader(自定义类)返回了一个ImageIcon的新实例。虽然它是相同的图像,但它是另一个实例。如果你反编译代码,你会发现对于JButton,setIcon将重新绘制和验证,如果newIcon!=oldIcon。

解决方法是在ResourceLoader中使用HashMap,这样可以避免加载图像超过一次,因为大多数图像非常频繁地使用(如果可以重用实例,那么最好)。结果,这个快速调整还以额外的优点节省了相当数量的整体内存消耗。


1
仍然不建议在paintComponent()方法中更改属性。您无法控制RepaintManager何时或多久调用该方法。如果您具有允许用户动态更改语言环境的功能,则还应该有一个例程,循环遍历所有受影响的组件并使它们更新自己,而不是定制每个组件的paintComponent()方法。 - camickr
我考虑过这个,但是这可能会非常快地变得异常复杂。试想一下尝试跟踪 Microsoft Outlook 中的每个组件。通过走这条路线,可以强制在主JFrame/JWindow上重绘,然后可以强制在所有子组件上重绘。而且作为额外的奖励,代码很少,最重要的是没有到处散布的代码来帮助区域设置管理器跟踪所有的组件等。 - Stephane Grenier

0
你是否在任何地方调用了 repaint() 方法?此外,当窗口变为可见(被揭开或最小化)或调整大小时,“系统”会自动调用 paintComponent() 方法来重新绘制屏幕上所有需要重绘的区域。

0
问题在于您正在paintComponent()方法中设置图标。您不应该在此方法中设置属性。
Swing组件足够智能,可以在属性更改时自动重绘自己。在这种情况下,由于图标更改而导致组件重新绘制本身的问题,但每次组件重新绘制本身时也会重新读取图标,这也不是很有效率的。

设置它的原因是,如果我更改区域设置,只需在父组件上触发事件,所有子组件将使用新文本重新绘制。 - Stephane Grenier

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