paintComponent在帧初始化后多次调用



考虑以下示例:

@SuppressWarnings("serial")
public static void main(final String[] args) {

final var frame = new JFrame();
frame.setPreferredSize(new Dimension(150, 150));
frame.add(new JPanel() {
@Override protected void paintComponent(final Graphics g) {
super.paintComponent(g);
System.out.println("painting panel");
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

SwingUtilities.invokeLater(() -> frame.setVisible(true));
}

有一个带有一个JPanel的JFrame,该JPanel具有重写的paintComponent方法,每次调用该方法时只需向控制台打印一些内容。每次我运行这个程序时,我都能看到"涂漆面板";在我的控制台上运行了3次。

为什么JPanel的方法paintComponent被调用多次而不是一次?有没有办法避免对部件进行不必要的重新喷漆?

本质上没有。但这并不像你想象的那样有问题。

绘画请求由底层系统的图形驱动程序控制。有时,应用程序可能只分配了少量的视频内存,在这种情况下,系统会一次绘制一个小窗口。

这意味着,仅仅因为paintComponent被多次调用并不意味着正在对该组件进行完全的重新绘制;在调用该方法之前,Graphics对象可能有一个片段设置为仅绘制窗口的一部分。paintComponent方法不需要关心这一点,因为如果大多数Graphics操作知道它们不会影响当前剪辑边界之外的任何像素,它们就会立即返回。这里的重点是,多次调用paintComponent并不一定像您想象的那样浪费。

此外,正如吉尔伯特所指出的,调用pack()将"实现"Window;也就是说,该窗口被分配了一个实际的本地桌面窗口。(Java称之为可显示。(这将触发绘制。显示窗口也可能触发绘制。移动它可能会触发绘制。将鼠标移到它上面可能会触发绘制。

对绘画的频率做出假设是不安全的。为了可靠地绘制,假设可以多次调用paintComponent方法。永远不要更改作为绘画方法基础的数据。

一般来说,绘画是无法控制的。当然,如果你的程序调用repaint,你可以控制调用的方式和时间。

最新更新