How to reduce the spacing between items in BoxLayout?

1

In my example, class Teste is JPanel with BorderLayout .

Within the middle of this layout is a JScrollPane containing another JPanel with BoxLayout vertically. The intent is for items I add to this JPanel to be placed in vertical list.

If you run the example and maximize the window they do this, but they are evenly distributed within JPanel and there are spaces between them, which is what I do not want. What I want is for them to occupy only the space needed to fit the layout and leave a large leftover underneath, as if I changed the commented parts of the code (change the addition of JPanelOrderRow to JLabels ).

The items I want to insert into the vertical list ( JPanelOrderRow ) are JPanels with GridBagLayout .

I would like to understand why this is happening and how do I get the desired effect.

Note: I can not use JList at this time because it would cause a lot of rework in the application I'm working on.

Test.java

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Teste extends JPanel {

    private static final long serialVersionUID = 1L;

    private JPanel jPanelListaOrders = new JPanel();
    private JScrollPane jScrollPaneOrders = new JScrollPane(jPanelListaOrders);

    public Teste() {

        this.setLayout(new BorderLayout());

        this.add(jScrollPaneOrders, BorderLayout.CENTER);

        jPanelListaOrders.setBackground(new java.awt.Color(254, 254, 254));
        jPanelListaOrders.setLayout(new javax.swing.BoxLayout(jPanelListaOrders, javax.swing.BoxLayout.Y_AXIS));

        // Adicionando somente esses quatro JPanelOrderRow, eles ficam
        // espaçados por igual no layout, o que não quero.
        jPanelListaOrders.add(new JPanelOrderRow());
        jPanelListaOrders.add(new JPanelOrderRow());
        jPanelListaOrders.add(new JPanelOrderRow());
        jPanelListaOrders.add(new JPanelOrderRow());

        // Adicionando somente esses quatro JLabels, fica uma sobra embaixo
        // deles que é o que desejo.
        //jPanelListaOrders.add(new JLabel("Teste"));
        //jPanelListaOrders.add(new JLabel("Teste"));
        //jPanelListaOrders.add(new JLabel("Teste"));
        //jPanelListaOrders.add(new JLabel("Teste"));
    }

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

            @Override
            public void run() {
                JFrame f = new JFrame("Teste");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(new Teste());
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}

JPanelOrderRow.java

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

public class JPanelOrderRow extends javax.swing.JPanel {

    private static final long serialVersionUID = 1L;

    public JPanelOrderRow() {
        initComponents();
        initializeData();
    }

    private void initializeData() {
    }

    private void initComponents() {

        setBackground(new java.awt.Color(254, 254, 254));
        setBorder(javax.swing.BorderFactory.createMatteBorder(0, 0, 1, 0, new java.awt.Color(237, 237, 237)));
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[] { 128, 0 };
        gridBagLayout.rowHeights = new int[] { 18, 0 };
        gridBagLayout.columnWeights = new double[] { 0.0, Double.MIN_VALUE };
        gridBagLayout.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
        setLayout(gridBagLayout);
        lblName = new javax.swing.JLabel();

        lblName.setFont(new java.awt.Font("Ubuntu", 1, 14)); // NOI18N
        lblName.setText("Nome do cliente");
        GridBagConstraints gbc_lblName = new GridBagConstraints();
        gbc_lblName.anchor = GridBagConstraints.SOUTH;
        gbc_lblName.fill = GridBagConstraints.HORIZONTAL;
        gbc_lblName.gridx = 0;
        gbc_lblName.gridy = 0;
        add(lblName, gbc_lblName);
    }
    private javax.swing.JLabel lblName;
}

    
asked by anonymous 28.11.2018 / 18:27

1 answer

1

BoxLayout will always resize everything inside it to occupy as much space as possible up to the maximum size defined by each component within it. Therefore, the gridbaglayout parameters in% internal% do not change the size of the components.

The same does not occur in JPanel because it has definitions that, unless you manually change its sizes, will always occupy the size required only to display its own content, is a feature of this component, and JLabel does not overlap with this because it respects the sizes defined by the component itself through the methods BoxLayout , setPreferredSize() and setMaximumSize() .

You will need to set a maximum size for the setMinimumSize() , the JPanel respects the data sizes for the components, when there is nothing informed, the maximum size is set to BoxLayout for width and height, and as long as there is space in the window, the layout will try to fill each component as much as possible until it reaches the maximum value defined by each.

The solution, removed from this SOEn response , looks silly but only exploits this BoxLayout feature by setting the size JPanel maximum for the preferred size, which is usually what is needed to compose its content, including borders and internal spacing. Just add the following line to the end of the method that builds JPanel Interger_MAX_VALUE and see the magic of layouts happen:

setMaximumSize(getPreferredSize());

Result:

    
28.11.2018 / 19:04