views:

292

answers:

2

I have a JPanel that encapsulates two JPanels, one on top of the other.

The first holds two JLabels which hold the playing cards.

The second holds the player's text (name and score).

However, when I remove the player's cards, the lower JPanel moves up to the top, which i would prefer that it not do. Is there a way to keep it in place regardless of whether the top JPanel is occupied or not?

Thanks

alt text

alt text

+1  A: 

What layout managers are you using? The default layout manager for a JPanel is a FlowLayout which render child components one after the other.

Maybe you could set the root JPanel to have a BorderLayout. Then set the top JPanel to the root panel's "top" spot:

JPanel rootPanel = ...;
JPanel topPanel = ...;
rootPanel.add(topPanel, BorderLayout.TOP);

Then set a minimum size for your top JPanel:

topPanel.setMinimumSize(new Dimension(someWidth, someHeight));

And add the second panel to the bottom or middle spot:

rootPanel.add(secondPanel, BorderLayout.CENTER);

Check out http://java.sun.com/docs/books/tutorial/uiswing/layout/border.html

Manuel Darveau
I think it's `BorderLayout.NORTH` rather than `BorderLayout.TOP`
Ash
It still produces what you see in the images below. I've reconfigured it as you recommended. The root panel is configured with borderLayout, the top panel is in BorderLayout.PAGE_START, and the lower panel is in BorderLayout.CENTER. To make the top panel hidden, i actually make each of the components hidden (the JLabels containing the cards that is)
Allen
and setMinimumSize for each of the JLabels containing the cards does not work either. Is it possible to put in a 'pseudo' component within the jpanel that'll just stay there and be transparent if the other components are hidden?
Allen
Ash: you are right, it's BorderLayout.NORTH.Allen: Try using BorderLayout.NORTH instead of BorderLayout.PAGE_START. I'm not sure what the difference is but I always used BorderLayout.NORTH.Don't set the minimum size on the JLabels but on the JPanel that holds the JLabels. Your "topPanel" will be in the "rootPanel"'s BorderLayout.NORTH portion and the "topPanel" will contains the cards. The JPanel default FlowLayout will be just fine to hold cards.
Manuel Darveau
Use setPreferedSize and not setMinimumSize. I forgot that BorderLayout uses prefered size and not minimum. From javadoc of BorderLayout: The components are laid out according to their preferred sizes and the constraints of the container's size. The NORTH and SOUTH components may be stretched horizontally; the EAST and WEST components may be stretched vertically; the CENTER component may stretch both horizontally and vertically to fill any space left over.
Manuel Darveau
A: 

I had time to do an example:

public class TestJpanel extends JFrame {


    public TestJpanel() {
        this.setLayout( new BorderLayout() );

        final JLabel card1 = new JLabel( "card1" );
        final JLabel card2 = new JLabel( "card2" );

        final JPanel topPanel = new JPanel();
        topPanel.setPreferredSize( new Dimension( 1024, 100 ) );
        topPanel.add( card1 );
        topPanel.add( card2 );

        this.add( topPanel, BorderLayout.NORTH );

        JPanel centerPanel = new JPanel();
        final JButton hideCardsButton = new JButton( "Hide cards" );
        hideCardsButton.addActionListener( new ActionListener() {

            @Override
            public void actionPerformed( ActionEvent e ) {
                if ( topPanel.getComponentCount() == 0 ) {
                    topPanel.add( card1 );
                    topPanel.add( card2 );
                    hideCardsButton.setText( "Hide cards" );
                } else {
                    topPanel.removeAll();
                    hideCardsButton.setText( "Show cards" );
                }
                topPanel.validate();
                topPanel.repaint();
            }
        } );
        centerPanel.add( hideCardsButton );

        this.add( centerPanel, BorderLayout.CENTER );
    }

    public static void main( String[] args ) {
        TestJpanel window = new TestJpanel();
        window.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
        window.setSize( 1024, 768 );
        window.setVisible( true );
    }

}

Note that this code if full of bad practices but helps demonstrate what I want with a short number of lines.

Manuel Darveau