Search code examples
javaswingborder-layoutjlayeredpane

Getting a panel within a JLayeredPane to stretch in a BorderLayout


I have the following basic arrangement:

+--- JFrame ---------------------------------------+
| +-- Panel --+ +-- JLayeredPane ----------------+ |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| |           | |                                | |
| +-----------+ +--------------------------------+ |
+--------------------------------------------------+

The panel on the left is on the WEST side of the JFrame's BorderLayout, and the JLayeredPane is in the CENTER. How can I get a panel on the DEFAULT layer of the JLayeredPane to stretch with the size of the JFrame?

I tried setting a BorderLayout on the JLayeredPane, but it fails with:

Caused by: java.lang.reflect.InvocationTargetException
  at java.awt.EventQueue.invokeAndWait(EventQueue.java:1349)
  at java.awt.EventQueue.invokeAndWait(EventQueue.java:1324)
  at org.rc.vitruvius.Vitruvius.main(Vitruvius.java:17)
Caused by: java.lang.IllegalArgumentException: cannot add to layout: constraint must be a string (or null)
  at java.awt.BorderLayout.addLayoutComponent(BorderLayout.java:426)
  at java.awt.Container.addImpl(Container.java:1130)
  at javax.swing.JLayeredPane.addImpl(JLayeredPane.java:231)
  at java.awt.Container.add(Container.java:975)

I'm using add(Component, LayerConstant), and I guess somehow that's incompatible with the border layout.

EDIT: Here's a small example to illustrate:

package sandbox;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

public class JLayeredPaneProblem extends JFrame
{
  private static final long serialVersionUID = 1L;

  public static void main(String[] args)
  {
    JLayeredPaneProblem main = new JLayeredPaneProblem();
    main.go();
  }
  
  public void go()
  {
    createMainUI();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
  }
  
  private void createMainUI()
  {
    JPanel leftPanel = getLeftPanel();
    Component middlePanel = getMiddlePanel(getOtherPanel());
    
    add(leftPanel, BorderLayout.WEST);
    add(middlePanel, BorderLayout.CENTER);
    pack();
  }
  
  private Component getMiddlePanel(JPanel wrappedPanel)
  {
    JLayeredPane middlePanel = new JLayeredPane();
    middlePanel.add(wrappedPanel, JLayeredPane.DEFAULT_LAYER);
    return middlePanel;
  }
  
  private JPanel getOtherPanel()
  {
    JPanel otherPanel = new JPanel();
    Dimension size = new Dimension(100,100);
    otherPanel.setSize(size);
    otherPanel.setPreferredSize(size);
    otherPanel.setBorder(BorderFactory.createLineBorder(Color.blue));
    return otherPanel;
  }
  
  private JPanel getLeftPanel()
  {
    JPanel innerPanel = new JPanel();
    innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.PAGE_AXIS));
    JButton button = new JButton("button");
    String [] items = { "One", "Two", "Three" };
    JComboBox<String> cbox = new JComboBox<>(items);
    innerPanel.add(button);
    innerPanel.add(cbox);
    
    JPanel leftPanel = new JPanel();
    leftPanel.add(innerPanel);
    
    
    return leftPanel;
  }
}

As you can see, the panel in the middle (blue border to see where its borders are) doesn't expand; I might have expected the JLayeredPane to expand and therefore the panel in its default (and other?) layers to expand, but none of them seem to. How is this supposed to be done?


Solution

  • I tried setting a BorderLayout on the JLayeredPane, but it fails with...:

    Add the component normally and then set the layer:

      private Component getMiddlePanel(JPanel wrappedPanel)
      {
        JLayeredPane middlePanel = new JLayeredPane();
        //middlePanel.add(wrappedPanel, JLayeredPane.DEFAULT_LAYER);
        middlePanel.setLayout(new BorderLayout() );
        middlePanel.add(wrappedPanel, BorderLayout.CENTER);
        middlePanel.setLayer(wrappedPanel, JLayeredPane.DEFAULT_LAYER);
        return middlePanel;
      }
    

    Using this approach there is no need for the ComponentListener.