Jordan H
Jordan H

Reputation: 55705

How to add two JPanels to a JFrame in the center?

I am creating a game which has a background image with cards displayed overtop. I would like to place the background image and cards such that they're always centered vertically and horizontally, even upon resizing the JFrame.

Currently, I am creating the cards (each a JPanel) and adding them into a container JPanel (no layout manager), then I add that Jpanel to the JFrame. After that I place the background image in a JPanel, then add that JPanel to the JFrame. The result is: The background image is hidden behind the cards and revealed when removing each card as desired. The background image is always centered but the card's JPanel does not move around upon resize. I am having a hard time getting the cards to always be centered, no matter what I try. I also need to add another JPanel to the JFrame in the South border, so that will need to work as well. I appreciate your assistance!

In the class that extends JFrame:

setSize(1060,700);

cardPanel = new JPanel();
cardPanel.setSize(1060,700);
cardPanel.setOpaque(false);
cardPanel.setLayout(null);
...card.setLocation(x, y); //loop through cards
...cardPanel.add(card); //and add each one
add(cardPanel, BorderLayout.CENTER); //add cardPanel to JFrame

//Add background image
bgPanel = new JPanel();
URL url = getClass().getResource("images/dragon_bg.png"); 
imgIcon = new ImageIcon(url);
JLabel background = new JLabel(imgIcon);
bgPanel.setLayout(new BorderLayout());
bgPanel.add(background);
add(bgPanel, BorderLayout.CENTER);

setVisible(true);

Upvotes: 0

Views: 2143

Answers (2)

Jordan H
Jordan H

Reputation: 55705

I ultimately decided to place the background image in the card panel itself, then put the card panel in a box layout manager so that it's always centered. I renamed cardPanel to gameBoard. Definitely could be cleaner, but I can only work with my requirements.

setSize(new Dimension(1000, 600));
gameBoard = new JPanel();
gameBoard.setLayout(null);
gameBoard.setOpaque(false);
Dimension expectedDimension = new Dimension(920, 500);
gameBoard.setPreferredSize(expectedDimension);
gameBoard.setMaximumSize(expectedDimension);
gameBoard.setMinimumSize(expectedDimension);
//add cards to gameBoard here

JLabel background = new JLabel( new ImageIcon( getClass().getResource("images/graphic.png") ) );
background.setLocation(79,0); //manually center graphic
background.setBounds(new Rectangle(0, 0, 920, 500));
gameBoard.add(background);

Box centerBox = new Box(BoxLayout.Y_AXIS);
centerBox.setOpaque(true); 
centerBox.setBackground(Color.WHATEVER);
centerBox.add(Box.createVerticalGlue());
centerBox.add(gameBoard);
centerBox.add(Box.createVerticalGlue());
add(centerBox);
setVisible(true);

Upvotes: -1

camickr
camickr

Reputation: 324108

I would like to place the background image and cards such that they're always centered vertically and horizontally, even upon resizing the JFrame.

Then you need to use layout managers on your panels. The layout manager is responsible for redoing the layout.

How to add two JPanels to a JFrame in the center?

You could try using the OverlayLayout for this. I think the basic code would be:

JPanel contentPane = new JPanel( new GrigBagLayo9ut() );
frame.add(contentPane, BorderLayout.CENTER);

JPanel overlay = new JPanel()
overlay.setLayout( new OverlayLayout(overlay) );
contentPane.add(overlay, new GridBagConstraints()); // this should center the overlay panel

overlay.add(yourCardPanel); // you care panel must use a suitable layout
overlay.add(new JLabel() ); // use a JLabel for the background not a custom panel

I also need to add another JPanel to the JFrame in the South border,

The default layout manager for a JFrame's content pane is a BorderLayout. We already added the game panel to the center, so know you just add your other panel to the SOUTH.

If the OverlayLayout doesn't work the way you want then you will need to nest panels. Something like:

JPanel center = new JPanel( new GridBagLayout() );
frame.add(center, BorderLayout.CENTER);

JLabel background = new JLabel(...);
background.setLayoutManager( new GridBagLayout() );
center.add(background, new GridBagConstraints());

background.add(yourCardPanel, new GridBagConstraints());

Edit:

Using nested panels:

import java.awt.*;
import javax.swing.*;

public class GridBagLayoutCenter extends JPanel
{
    public GridBagLayoutCenter()
    {
        setLayout( new BorderLayout() );

        JLabel background = new JLabel( new ImageIcon("mong.jpg") );
        background.setLayout( new GridBagLayout() );

        add(background, BorderLayout.CENTER);

        JPanel tiles = new JPanel();
        tiles.setPreferredSize( new Dimension(200, 200) );
        tiles.setBackground( Color.RED );
        background.add(tiles, new GridBagConstraints());

        add(new JLabel("SOUTH"), BorderLayout.SOUTH);
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("GridBagLayoutCenter");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new GridBagLayoutCenter() );
        frame.setSize(400, 400);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

The preferred size of the "tiles" panel should not be hardcoded. The size should be determined by your custom layout manager based on the tiles that you add to the panel. The size should not change as tiles are removed.

Upvotes: 3

Related Questions