3

The below code represents the problem. Since I have heights of the north and south panels set the rest of it goes to the center panel using GridLayout. I think that since it cannot share the leftover pixels equally among its rows it just leaves them. Therefore in the below code we have ugly white line over south panel.

My question here is: How to make sure that when the GridLayout is not taking the whole space it is at least centered?

Normally I would use TableLayout and situation is sorted, but since I was writing an answer I wanted to use only standard managers. Knowing this would be very useful for me thanks in advance.

Example:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class AligningButonsTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {                   
                JFrame f = new JFrame();
                f.setSize(800, 600);
                double CONSTANT_FACTOR = .1;
                int noOfRows = 5;
                JPanel centerP = new JPanel(new GridLayout(noOfRows,1));

                for(int i = 0; i < noOfRows; i++)
                {   
                    BoxPanel bP = new BoxPanel();
                    centerP.add(bP);
                }
                JPanel contentPane = new JPanel(new BorderLayout());                
                f.setContentPane(contentPane);
                contentPane.add(centerP, BorderLayout.CENTER);
                JPanel southP = new JPanel();
                southP.setBackground(Color.RED.darker());//southP.setOpaque(false);
                southP.setPreferredSize(new Dimension(1, (int)(CONSTANT_FACTOR* f.getHeight())));
                contentPane.add(southP, BorderLayout.SOUTH);
                JPanel northP = new JPanel();
                northP.setBackground(Color.RED.darker());//northP.setOpaque(false);
                northP.setPreferredSize(new Dimension(1, (int)(CONSTANT_FACTOR* f.getHeight())));
                contentPane.add(northP, BorderLayout.NORTH);            
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }   
}

class BoxPanel extends JPanel
{
    public BoxPanel()
    {
        setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.RED));
        setBackground(Color.DARK_GRAY);
    }   
}
Boro
  • 7,913
  • 4
  • 43
  • 85
  • there is problem, that some LayoutManager ignored on Resize for PrefferedSize (BorderLayout, GridLaoyut), because are wraped to the locations or Grid, as I know only GridBag can use anchor + PrefferedSize directly and together, sure there are must exist simple hack/workaroud for that ... – mKorbel May 20 '11 at 14:43
  • +1 @camicker @msj121 @trashgod I will give you points tomorrow, I have spent all for today. I consider the centring issue sorted thanks. Now I would love to know how to fill the left over space. From what I understand this is beyond capabilities of the GridLayout. Thus, I wonder how to make sure that e.g. GridBagLayout will fill all space of e.g. first and/or last row. I tried GridBagConstraints.weighty = 1.0 as in the tutorial example but no good. Though in contrary to tutorial example my width is always perfectly filled. Is it the problem specific to this layout? – Boro May 20 '11 at 19:26

3 Answers3

4

How to make sure that when the GridLayout is not taking the whole space it is at least centered?

JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add( centerP );
contentPane.add(wrapper, BorderLayout.CENTER);  
//contentPane.add(centerP, BorderLayout.CENTER); 
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thanks for that. OK this does the centring bit thought it doesn't make sure the centerP takes the whole space. And I wouldn't like a solution that would require me to setPreferredSize for the centerP. – Boro May 20 '11 at 16:43
3

BoxLayout does a pretty good job of distributing the space between components using Box.createVerticalGlue(). This example uses Box.createVerticalStrut(), top and bottom. The spacers are described in How to Use BoxLayout: Using Invisible Components as Filler.

Addendum: BoxTest2 is a variation that uses BoxLayout to create fixed-size edge panels and vertical glue to distribute the space more evenly. Box.Filler may also be used to control the "leftover" vertical space.

/** @see http://stackoverflow.com/questions/6072956 */
public class BoxTest2 {

    private static final int WIDE = 480;
    private static final int HIGH = WIDE / 8;
    private static final int ROWS = 5;
    private static final Box center = new Box(BoxLayout.Y_AXIS);

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

            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                center.setOpaque(true);
                center.setBackground(Color.lightGray);
                center.add(Box.createVerticalGlue());
                center.add(new EdgePanel());
                for (int i = 0; i < ROWS; i++) {
                    center.add(new BoxPanel());
                }
                center.add(new EdgePanel());
                center.add(Box.createVerticalGlue());
                f.add(center, BorderLayout.CENTER);
                f.pack();
                f.setVisible(true);
            }
        });
    }

    private static class EdgePanel extends JPanel {

        public EdgePanel() {
            Dimension d = new Dimension(WIDE, 2 * HIGH / 3);
            setPreferredSize(d);
            setBackground(Color.red.darker());
        }
    }

    private static class BoxPanel extends JPanel {

        public BoxPanel() {
            setPreferredSize(new Dimension(WIDE, HIGH));
            setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.red));
            setBackground(Color.darkGray);
        }
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • @Boro: IIUC, `GridLayout` tries to apportion space equally, but your `noOfRows` may not be an integral multiple of the center panel's height. In the example above, I've commented out the struts to highlight the effect. As you enlarge the window, you'll see 0…4 light gray rows appearing cyclically across the bottom of the center panel. – trashgod May 21 '11 at 00:41
  • @trashgod I though it must be it. Thus I started to play with GridBagLayout, to get it fill the last row with the rest, and I observed that it also is not accurate with this. It is observable as I have mentioned even in the example in its tutorial, though in their case the problem is observable with the width. – Boro May 21 '11 at 00:54
  • @Boro: Our examples tend to use contrasting colors to highlight the effects; but a non-opaque component will let the L&F default show. For reference, I've added another variation above. The previous version remains in [revisions](http://stackoverflow.com/posts/6076340/revisions). – trashgod May 21 '11 at 15:15
  • @trashgod Your answer and all the input was the most useful. Thus, I am accepting your answer. Thanks again. Sadly I do not see a solution being achievable using default managers. Hopefully one day they will integrate some more advanced layout manager which takes care of such details. I heard that it might be MiG Layout. Did you have some experience with it? – Boro May 23 '11 at 07:56
  • @Boro: Sorry, relatively little. I updated the example to remove some noise in `EdgePanel`. – trashgod May 23 '11 at 12:03
2

Could you try perhaps nesting this center panel in either a BorderLayout.North or maybe even a FlowLayout.Center.

By this I mean: JPanel holder = new JPanel(new BorderLayout()); holder.add(centerP,BorderLayout.NORTH); contentPane.add(holder, BorderLayout.CENTER);

I cannot exactly visualize your problem so it is hard to write a solution.

msj121
  • 2,812
  • 3
  • 28
  • 55
  • Thanks for the input. What I am trying to achieve is to find a solution to be able to use GridLayout for rows and columns setting, while centring it. – Boro May 20 '11 at 16:51