JLayeredPane not resizing with JFrame

2019-08-27 16:04发布

问题:

I have a JLayeredPane within a JFrame, with two JPanels in it. It all works fine, except since the JLayeredPane requires me to have a null Layout, it doesn't resize the two JPanels correctly when the JFrame resizes.

public class CreatorUI extends JFrame{

    private static final long serialVersionUID = 1L;

    private JPanel moveablePane = new JPanel();
    private Container backgroundPane;
    private JLayeredPane layers = new JLayeredPane();
    private ComponentMover componentMover = new ComponentMover();
    private ComponentResizer componentResizer = new ComponentResizer();

    public CreatorUI(){
        backgroundPane = new BackgroundUI().initComponents();

        layers.add(backgroundPane, 1);
        moveablePane.setLayout(null);
        componentMover.setAutoLayout(true);
        moveablePane.setOpaque(false);
        layers.add(moveablePane, 2);
        moveablePane.setSize(backgroundPane.getSize());
        add(layers, BorderLayout.CENTER);
        layers.setPreferredSize(backgroundPane.getPreferredSize());

        pack();
    }

    public void addWindow(WindowComponent window){
        this.componentMover.registerComponent(window);
        this.componentResizer.registerComponent(window);

        this.componentMover.setDragInsets(this.componentResizer.getDragInsets());

        this.moveablePane.add(window);
    }


    public static void main(String[] args){
        CreatorUI frame = new CreatorUI();

        frame.addWindow(new MapComponent());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

}

This is what it looks like normally (looks perfect for the normal size):

This is what it looks like once I've tried to resize the JFrame:

I figured out that I can make the top layer resizable if I change my code to this:

public CreatorUI(){

    componentMover.setAutoLayout(true);

    backgroundPane = new BackgroundUI().initComponents();
    moveablePane.setLayout(null);
    moveablePane.setOpaque(false);
    moveablePane.setSize(backgroundPane.getSize());

    layers.setLayout(new BorderLayout());
    layers.add(backgroundPane, BorderLayout.CENTER);
    layers.setLayer(backgroundPane, new Integer(1));
    layers.add(moveablePane, BorderLayout.CENTER);
    layers.setLayer(moveablePane, new Integer(2));

    add(layers, BorderLayout.CENTER);
    layers.setPreferredSize(backgroundPane.getPreferredSize());

    pack();
}

This is what it look like now (only the pink layer resizes):

回答1:

I have the same problem with a more complex container with a shadow Layer above. I was searching for an answer but only found this (which was not helping me). What i did was this:

layers.addComponentListener(new ComponentAdapter() {
    @Override public void componentResized(ComponentEvent e) {
        Dimension size = layers.getSize(); // get size
        backgroundPane.setSize(size); // push size through
        moveablePane.setSize(size); // push size trhough
//      otherChildOfLayers.setSize(size); // push size trhough
        layers.revalidate(); // revalidate to see updates
        layers.repaint(); // "Always invoke repaint after revalidate"
    }
});

some more information about repaint/revalidate



回答2:

Answering my own question

There is a very hack-y fix, which (for your purposes) is to keep the overlay at max size at all times.

public CreatorUI(){

    componentMover.setAutoLayout(true);

    backgroundPane = new BackgroundUI().initComponents();
    moveablePane.setLayout(null);
    moveablePane.setOpaque(false);
    moveablePane.setSize(Toolkit.getDefaultToolkit().getScreenSize());

    layers.setLayout(new BorderLayout());


    layers.setLayer(moveablePane, JLayeredPane.DRAG_LAYER);
    layers.add(moveablePane, BorderLayout.CENTER);

    layers.setLayer(backgroundPane, JLayeredPane.DEFAULT_LAYER);
    layers.add(backgroundPane, BorderLayout.CENTER);


    add(layers, BorderLayout.CENTER);
    layers.setPreferredSize(backgroundPane.getPreferredSize());

    pack();
}