问题
I have a window that has two layers: a static background and a foreground that contains moving objects. My idea is to draw the background just once (because it's not going to change), so I make the changing panel transparent and add it on top of the static background. Here is the code for this:
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);
}
This piece of code gives me the correct image I want, but every time I repaint changingPanel
, staticPanel
gets repainted as well (which is obviously against the whole idea of painting the static panel just once). Can somebody show me what's wrong?
FYI I am using the javax.swing.Timer to recalculate and repaint the changing panel 24 times every second.
回答1:
When you repaint a transparent component above another, you still 'dirty' the lower component, causing it the be repainted. If you didn't repaint the lower layer, you would get a smearing effect of the image on top of it.
The only optimisation available here is not regenerating the image used on the lower level. The raster still needs to be painted to the graphics buffer every time the layer above changes.
回答2:
This is exactly the way painting works. Swing has to search for the first component that has a non-opaque background. Then it paints that component and the children to make sure all the painting is done correctly.
Even if you have a moving compnent, SWing would still need to "clear" the last position of the compnent, which means it has to at least repaint that area of the background panel, before repaint the component that moved.
To make the painting more efficient the child panel should be opaque. I don't know why you changed the default setting.
回答3:
A really easy way is to use jxlayer. Implement AbstractLayerUI and add that over your component. See here to get started.
来源:https://stackoverflow.com/questions/2696285/jframe-that-has-multiple-layers