Java Swing - how to show a panel on top of another panel?

118,363

Solution 1

I think LayeredPane is your best bet here. You would need a third panel though to contain A and B. This third panel would be the layeredPane and then panel A and B could still have a nice LayoutManagers. All you would have to do is center B over A and there is quite a lot of examples in the Swing trail on how to do this. Tutorial for positioning without a LayoutManager.

public class Main {
    private JFrame frame = new JFrame();
    private JLayeredPane lpane = new JLayeredPane();
    private JPanel panelBlue = new JPanel();
    private JPanel panelGreen = new JPanel();
    public Main()
    {
        frame.setPreferredSize(new Dimension(600, 400));
        frame.setLayout(new BorderLayout());
        frame.add(lpane, BorderLayout.CENTER);
        lpane.setBounds(0, 0, 600, 400);
        panelBlue.setBackground(Color.BLUE);
        panelBlue.setBounds(0, 0, 600, 400);
        panelBlue.setOpaque(true);
        panelGreen.setBackground(Color.GREEN);
        panelGreen.setBounds(200, 100, 100, 100);
        panelGreen.setOpaque(true);
        lpane.add(panelBlue, new Integer(0), 0);
        lpane.add(panelGreen, new Integer(1), 0);
        frame.pack();
        frame.setVisible(true);
    }


    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Main();
    }

}

You use setBounds to position the panels inside the layered pane and also to set their sizes.

Edit to reflect changes to original post You will need to add component listeners that detect when the parent container is being resized and then dynamically change the bounds of panel A and B.

Solution 2

You can add an undecorated JDialog like this:

import java.awt.event.*;

import javax.swing.*;

public class TestSwing {
  public static void main(String[] args) throws Exception {
    JFrame frame = new JFrame("Parent");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(800, 600);
    frame.setVisible(true);

    final JDialog dialog = new JDialog(frame, "Child", true);    
    dialog.setSize(300, 200);
    dialog.setLocationRelativeTo(frame);
    JButton button = new JButton("Button");
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        dialog.dispose();
      }
    });
    dialog.add(button);
    dialog.setUndecorated(true);
    dialog.setVisible(true);
  }
}

Solution 3

I just thought that I'd add that there is a notion of Z-order in Swing, see [java.awt.Component#setComponentZOrder][1]

which affects the positions of a component in its parents component array, which determines the painting order.

Note that you should override javax.swing.JComponent#isOptimizedDrawingEnabled to return false in the parent container to get your overlapping components to repaint correctly, otherwise their repaints will clobber each other. (JComponents assume no overlapping children unless isOptimizedDrawingEnabled returns false)

[1]: http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Container.html#setComponentZOrder(java.awt.Component, int)

Solution 4

Use a 1 by 1 GridLayout on the existing JPanel, then add your Panel to that JPanel. The only problem with a GridLayout that's 1 by 1 is that you won't be able to place other items on the JPanel. In this case, you will have to figure out a layout that is suitable. Each panel that you use can use their own layout so that wouldn't be a problem.

Am I understanding this question correctly?

Share:
118,363
Pool
Author by

Pool

Updated on August 02, 2022

Comments

  • Pool
    Pool almost 2 years

    I wish to have an internal (non window) dialog to ask for member input. I would like the dialog to be placed centrally on an existing JPanel.

    I have looked at layeredpanes and these seem unusable due to only having a single layout manager (or no layout manager) across all the panes. I guess I could try to override JLayeredPane and provide a custom layout but this seems extreme.

    Glass panes don't seem to be appropriate either.

    How can this be done? Is there no usable concept of z-indexes in Swing?

    EDIT

    The reason Layered Panes weren't appropriate was due to the lack of a layout manager per layer. The panel is resizeable, Panel A should stay at 100% of area and Panel B should stay centralized.

  • Pool
    Pool about 15 years
    Thanks, I've added a diagram above to clarify. Basically it's laying the components on top of each other (z index) that I'm unsure about.
  • Pool
    Pool about 15 years
    Hi, this is the avenue I was initially pursuing but I can't figure out how to make A and B behave without using setBounds. The docs for JLayeredPane mentions "All of the layout managers provided by the Java platform arrange the components as if they were all on one layer.".
  • AlbertoPL
    AlbertoPL about 15 years
    Oh ok I see, my mistake. Thanks for the extra clarification.
  • Rémi Vennereau
    Rémi Vennereau about 15 years
    Yes that is correct. To position A and B you need to use setBounds. The panels A and B can still have whatever LayoutManager you want to position components within them. Does that answer your question?
  • Pool
    Pool about 15 years
    The reason I was trying to use a layout manager over setBounds is that the panel can be resized. Possibly extending JLayeredPane, listening for component changes and calling setBounds on it's children is a correct way to solve this. (I'll edit original question to clarify this too.)
  • Pool
    Pool about 15 years
    Thanks, unfortunately this creates a new window, +1 for undecorated though, very nice effect.
  • mavroprovato
    mavroprovato about 15 years
    And why this is a problem? Now that I look at you question for a second time, you may want to make the dialog non modal and reposition it when the parent frame is resized.
  • Pool
    Pool about 15 years
    It's a requirement. A dialog / window would not make sense for this panel.