Search code examples
javaswing

Pack swing elements at top of panel


Given the following code:
(Not my actual code, just the simplest code I could knock together which repros the issue)

package com.example;

import javax.swing.Box;
import javax.swing.BoxLayout;
import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
 
public class JTableExample {
    JFrame f;
    JTable table;
 
    JTableExample()
    {
        f = new JFrame();
        f.setTitle("JTable Example");
        String[][] data = {
            { "Kundan Kumar Jha", "4031", "CSE" },
            { "Anand Jha", "6014", "IT" }
        };
 
        String[] columnNames = { "Name", "Roll Number", "Department" };
 
        JPanel outerPanel = new JPanel();
        outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS));

        for (int i = 0 ; i < 3; i++){
            JPanel tablePanel = new JPanel(new BorderLayout());
            table = new JTable(data, columnNames);
            tablePanel.add(table.getTableHeader(), BorderLayout.PAGE_START);
            tablePanel.add(table, BorderLayout.CENTER);
            outerPanel.add(tablePanel);
            outerPanel.add(Box.createRigidArea(new Dimension(0,20)));
        }
 
        JScrollPane sp = new JScrollPane(outerPanel);
        f.add(sp);
        f.setSize(500, 400);
        f.setVisible(true);
    }
 
    public static void main(String[] args)
    {
        new JTableExample();
    }
}

You get a window which looks like so: enter image description here

What I want is for the tables to all be packed at the top of the window, with all the blank space at the bottom, like so:
(I bodged this screenshot by adding 20 JPanels after the tables) enter image description here

I have attempted to use a GridBagLayout, but what ends up happening is this:
(Everything just floating in the middle of the window)
enter image description here

Can anyone help me understand what I am doing wrong?
In case it matters, in my actual code, there is an arbitrary number of tables, it's not fixed.


Solution

  • A BoxLayout will allocate extra space to each component up to the maximum size of the component. Since the panels maximum size is far greater than the preferred size of the panel you get the extra space.

    One way to solve this problem is to use a "wrapper" panel to force the table panels to be displayed at their preferred height:

    JPanel wrapper = new JPanel( new BorderLayout() );
    wrapper.add(outerPanel, BorderLayout.PAGE_START);
    JScrollPane sp = new JScrollPane(wrapper);
    //JScrollPane sp = new JScrollPane(outerPanel);
    

    Another option would be to override the getMaximumSize() method of your table panel to set the maximum height to the preferred height.

    Something like:

    JPanel tablePanel = new JPanel(new BorderLayout())
    {
        @Override
        public void getMaximumSize()
        {
            Dimension preferred = getPreferredSize();
            Dimension maximum = getMaximumSize();
            maximum.height = preferred.height;
    
            return maximum;
        }
    };