javaswingjbuttonboxlayoutjlayeredpane

Can I use BoxLayout on a JLayeredPane to space items on each layer individually?


I am creating Uno as my final project in my CompSci class.
The cards in playerHandPanel are made of JButtons. The buttons should be displayed sequentially in the order they were dealt, but also should be overlapping to fit more than the starting 7 cards in the panel.

My teacher suggested I use JLayeredPane instead of JPanel as the container because items can be put on different layers.
It didn't work because I was using BoxLayout to auto-place them with LINE_AXIS and that layout completely ignores the layers and spaces them as if it was a normal JPanel.

BoxLayout ignoring the layers:
BoxLayout ignoring the layers

Rather, they should overlap like this:
They should overlap like this

This is how playerHandPanel is set up:

    public void setupImgs()
    {
        //gets the dealt hand and sets up the buttons/imgs
        for (int i = 0; i < deck.getPlayerHand().size(); i++)
        {
            setupHand(new JButton(deck.getHandImgs().get(i)), i);
        }
    }
    public void setupHand(JButton img, int index)
    {
        //TODO allow more than 7 cards in hand
        //TODO jlayeredpane to allow overlap by using layers
        //boxlayout puts them in sequential but ignores layers >:(

        playerHandPanel = new JLayeredPane();
        playerHandPanel.setBounds(250, 350, 1400, 300);
        playerHandPanel.setBackground(Color.GRAY);
        playerHandPanel.setLayout(new BoxLayout(playerHandPanel, BoxLayout.LINE_AXIS));
        //using the 

        if (index == 0)
        {
            //playerHand1
            ph1 = new JButton("", img.getIcon());
            ph1.setSize(150, 240);
            ph1.setLocation(0, 0);
            ph1.setMargin(new Insets(1,1,1,1));
            ph1.addActionListener(this);
            ph1.addMouseListener(this);//moves up when card focused
            playerHandPanel.add(ph1, JLayeredPane.DEFAULT_LAYER);
            //placed on bottom-most layer
        }

        if (index == 1)
        {
            ph2 = new JButton("", img.getIcon());
            ph2.setSize(150, 240);
            ph2.setLocation(20, 0);
            ph2.setMargin(new Insets(1,1,1,1));
            ph2.addActionListener(this);
            ph2.addMouseListener(this);
            playerHandPanel.add(ph2, JLayeredPane.PALETTE_LAYER);
            //placed on second lowest layer

        }
        
        if (index == 2)
        {
            ph3 = new JButton("", img.getIcon());
            ph3.setSize(150, 240);
            ph3.setLocation(50, 0);
            ph3.setMargin(new Insets(1,1,1,1));
            ph3.addActionListener(this);
            ph3.addMouseListener(this);
            playerHandPanel.add(ph3, JLayeredPane.MODAL_LAYER);
            //placed on third lowest layer
        }
        //continued to 7...
        window.add(playerHandPanel);
        playerHandPanel.setVisible(true);
    }

I tried using one or two other layouts, like but couldn't really figure out how they worked. In the end I just went back to BoxLayout. I tried GroupLayout because I thought I could group cards a certain way across layers. I don't really know how to explain it, but it doesn't really matter because it didn't work.
I tried to draw it though


Solution

  • This is what I needed, thanks to @camickr for the comment. This is very simple and as I said, I don't have much time to try something completely new.
    "Check out the Overlap Layout. Think you can also use the FlowLayout with a negative horizontal gap. You will also need to override the isOptimizedDrawingEnabled() to return false on the panel." -@camickr

    I will also be adding a rule where the Hgap changes when cards are added to the hand.