gpt4 book ai didi

java - 多次调用paintComponent且组件重叠

转载 作者:行者123 更新时间:2023-11-30 03:21:17 25 4
gpt4 key购买 nike

我有几个 JPanel 在父 JPanel 内彼此层叠。当我对其中一个调用 repaint() 时,所有这些都会重新绘制与层数一样多的次数。这会呈二次方增长!对于 3 个面板,我看到每个面板有 3 次重绘,即 9 次重绘。 5 个面板有 25 次重绘。

我发现对于重叠组件,我应该重写父级中的 isOptimizedDrawingEnabled() 并返回 false。或者使用 JLayeredPane 作为父级。我都尝试了,结果是一样的。

这是什么原因造成的?

如何阻止我的面板多次重新绘制?

编辑: SSCCE/MCVE 如下:

public class JPanelTest extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JPanelTest();
}
});
}

public JPanelTest() {
super(null);
setLayout(new OverlayLayout(this));

JFrame f = new JFrame(getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 600);

final Model model = new Model();

f.getContentPane().add(this);
this.add(new MyPanel(model));
this.add(new MyPanel(model));
this.add(new MyPanel(model));
this.add(new MyPanel(model));
this.add(new MyPanel(model));

f.setLocationRelativeTo(null);
f.setVisible(true);

addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent ex) {
model.setColor(new Color((int)ex.getWhen()));
}
});
}

@Override
public boolean isOptimizedDrawingEnabled() {
return false;
}
}

// My own containers/listeners/events are larger, so this is shorter for SSCCE/MCVE.
class Model extends PropertyChangeSupport {
Color color = Color.BLACK;

public Model() {
super(Color.BLACK);
}

public void setColor(Color color) {
this.color = color;
firePropertyChange("color", null /* meh */, color);
}
}

class MyPanel extends JPanel implements PropertyChangeListener {
static int instanceCounter = 0;
int repaintCounter = 0;
final int instance;

private Model model;

public MyPanel(Model model) {
super(null);
instance = ++instanceCounter;
setOpaque(false);

this.model = model;
model.addPropertyChangeListener(this);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);

g.setColor(model.color);
g.drawString("panel " + instance + ", repaint " + ++repaintCounter, 1, instance * 15);
}

@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("panel " + instance + ": Value is now " + evt.getNewValue());
repaint();
}
}

一些额外的说明:我注意到,对于每个要多次重绘的面板,我必须多次调用 repaint() 。但是,当所有面板并排(不重叠)时,它们都会重新绘制一次。

最佳答案

What is causing this?

我猜原因是因为所有面板都是非透明的。

绘制非不透明组件时,RepaintManager 必须找到第一个不透明父组件,然后绘制父组件和所有子组件。这种情况发生 5 次,因此您会重画 25 次。

在您的简单示例中,您可以更改 propertyChanged(...) 方法中的代码:

getParent().repaint();

现在将在父容器而不是单个面板上发出 5 个重绘请求。 RepaintManager 会将这些请求组合成一个请求,然后面板及其 5 个子面板将被绘制一次。

关于java - 多次调用paintComponent且组件重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31271989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com