poke
poke

Reputation: 388113

Fixed width, variable height in JPanel with flow

I have an annoying problem with Java’s layout managers. I have the following situation: In a panel A are two other panels B with an absolute layout and C with a FlowLayout. B is highly customized and has a fixed size set via setPreferredSize. C should have the same fixed width as B but otherwise be of a variable height, depending on how many components are added in the flow. The resulting A should then have the fixed width and A.height + B.height as the height – at least that is what I want.

However what I get is that the width of the panel A is not fixed at all (even if I set its preferred size), and the contents in panel C are not automatically wrapping but instead are displayed in a long line. Of course this also makes B having a larger width than it should be.

What can I do to fix that? Is there any better layout, or do I have to emulate that all using an absolute layout?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Test extends JPanel
{
    public Test ()
    {
        this.setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );

        JPanel top = new JPanel( null );
        top.setBackground( Color.GREEN );
        top.setPreferredSize( new Dimension( 200, 20 ) );
        JPanel flowPanel = new JPanel( new FlowLayout( FlowLayout.LEFT, 2, 2 ) );

        this.add( top );
        this.add( flowPanel );

        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
        flowPanel.add( new JButton( "x" ) );
    }
}

Upvotes: 7

Views: 33255

Answers (4)

Doume
Doume

Reputation: 1

Everything you put in a LINE_END or LINE_START part of a BorderLayout will keep its width constant : Only height will be resized if container is resized

NORTH and SOUTH are width variable

CENTER is width & height variable

LINE_START & LINE_END are only height variable

So, I suggest you put your 'C' container in this kind of BorderLayout area

Upvotes: 0

Aaron Digulla
Aaron Digulla

Reputation: 328774

  1. You shouldn't add children to the frame directly. Always add to the contentPane -> this.getContentPage().add(...)

  2. To make your layout work, put a JPanel with a GridBagLayout in the content page and make that panel fill the content page.

  3. Give the GridBagLayout 2 columns.

Now you can't disable horizontal resizing of the window, so you must find a different way to handle the extra space. I suggest to give the first column a fixed width (set fill=NONE) and let the panel C fill the remaining space.

If you set all the sizes (min,max,preferred) of the panel B to the preferred size, it should not change it's size anymore.

Tip: If a Swing layout doesn't work, nest it in another layout.

Upvotes: 0

camickr
camickr

Reputation: 324147

Wrap Layout should help.

Upvotes: 10

Riduidel
Riduidel

Reputation: 22300

The best way to provide the kind of advanced view configuration you desire is by replacing you FlowLayout by the powerful GridBagLayoutManager. It's worth to note that the constraints, expressed usually by GridBagConstraints, are by far easier to understand when using fluent subclasses, like GBC.

Finally, like always, you should consider taking a look at the Swing tutorial.

Upvotes: 0

Related Questions