开发者

How to correct/center GridLayout using standard Java layout managers?

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);
               开发者_JAVA百科 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);
    }   
}


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); 


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);
        }
    }
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜