我有一个有两层的窗口:静态背景和包含移动对象的前景。我的想法是只绘制一次背景(因为它不会改变),所以我将更改面板透明并将其添加到静态背景之上。以下是此代码:
public static void main(String[] args) {
JPanel changingPanel = new JPanel() {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(100, 100, 100, 100);
}
};
changingPanel.setOpaque(false);
JPanel staticPanel = new JPanel();
staticPanel.setBackground(Color.BLUE);
staticPanel.setLayout(new BorderLayout());
staticPanel.add(changingPanel);
JFrame frame = new JFrame();
frame.add(staticPanel);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
这段代码为我提供了我想要的正确图像,但每次重新绘制changingPanel
时,staticPanel
也会被重新绘制(这显然违背了仅仅绘制一次静态面板的想法)。有人能告诉我什么是错的吗?
仅供参考我使用javax.swing.Timer每秒重新计算和重新绘制更改面板24次。
答案 0 :(得分:7)
当您将透明组件重新绘制在另一个组件上方时,您仍然会“弄脏”下方组件,从而使其重新绘制。如果您没有重新绘制下层,则会在其上方获得图像的拖尾效果。
此处唯一可用的优化不是重新生成较低级别上使用的图像。每当上面的图层发生变化时,仍然需要将光栅绘制到图形缓冲区。
答案 1 :(得分:3)
这正是绘画的作用方式。 Swing必须搜索具有非不透明背景的第一个组件。然后它绘制该组件和孩子,以确保所有绘画都正确完成。
即使你有一个移动的组件,SWing仍然需要“清除”组件的最后位置,这意味着它必须至少重新绘制背景面板的那个区域,然后重新绘制移动的组件。
为了使绘画更有效,子面板应该是不透明的。我不知道为什么你改变了默认设置。
答案 2 :(得分:2)
一种非常简单的方法是使用jxlayer。实施AbstractLayerUI并将其添加到您的组件上。请参阅here开始使用。