views:

198

answers:

3

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" ) );
    }
}
+1  A: 

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.

Riduidel
Hmm, thanks for the links (especially GBC ^^), however I'm not sure how to reproduce the effect FlowLayout gave me with the GridBagLayout. I actually do want to wrap those components (here: buttons) into the next line, that don't have enough room because of the fixed width of the parent JPanel.
poke
A: 
  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.

Aaron Digulla
Regarding point 1: "As a convenience, `add` and its variants, `remove` and `setLayout` have been overridden to forward to the `contentPane` as necessary." http://download.oracle.com/javase/6/docs/api/javax/swing/JFrame.html
trashgod
Note that I'm not working inside of a Frame/Window, but that my actual class above is a JPanel itself. It is the panel *A* from my description and is used in a different layout which layout won't change its size.
poke
@trashgod: That's since Java 6.
Aaron Digulla
@poke: Ah. Then give panel A a GridBagLayout, 2 columns, same width (give them the same weight).
Aaron Digulla
The forwarding convenience appeared in Java 5, ca 2004. http://download.oracle.com/javase/1.5.0/docs/api/javax/swing/JFrame.html
trashgod
+3  A: 

Wrap Layout should help.

camickr
That actually works quite well! If nobody comes up with a native solution, this is what I'll be going with. Thank you! Just too bad that the standard layout managers keep failing in such common (at least to me) situations, and you always end up with a new custom one.. :/
poke
@poke: For me, this represents a kind of selection bias—I tend to forget that standard layouts usually just work! `WrapLayout` is also a good example of writing one's own manager.
trashgod