JFrame that has multiple layers

筅森魡賤 提交于 2020-01-03 21:18:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!