How to reduce the spacing between items in Boxlayout?

Asked

Viewed 227 times

1

In my example, the class Teste is a JPanel with BorderLayout.

Within the central region of this layout there is a JScrollPane containing another JPanel with BoxLayout vertically. The intention is that the items I add to that JPanel are listed vertically.

If you run the example and maximize the window they do this, but are distributed equally within the JPanel and there are spaces between them, which is what I don’t want. What I wish is that they only take the space necessary to fit in the layout and leave a large leftover underneath, as happens if I change the commented parts of the code (change the addition of JPanelOrderRow for JLabels).

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

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

Note: I cannot use JList at the moment because it would provoke a lot of rework in the application I am working on.

Java test.

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

Espaçamento indesejado entre as linhas

Sem espaçamento e com uma sobra embaixo, que é o desejado

  • Where is the spacing?

  • Sorry, I forgot to tell you. You have to maximize the window to see.

  • The cause is the same as I said in the other question, it is due to your layout, you are mixing a lot of different layouts.

  • I’m mixing it because I imagine Swing works like this, with different layouts anyway. I have Boxlayout to compose a list of elements and each element has a Gridbaglayout layout. What’s the problem with that? What should I do instead?

  • boxlayout will always resize everything inside it to occupy as much space as possible until all are distributed inside the window, it is useless to define gridbaglayout parameters in the internal Jpanel, because the most external layout (boxlayout) is that will set the distribution and this is not changeable unless you rewrite the layout manually.

  • The same does not occur in Jlabel because it has settings that, unless you set manual sizes relative to the screen size, it will always occupy the size needed only to display its own content, is a feature of the Jlabel component, and the layout does not overlap with that.

  • Got it! I tried changing the JLabel by a JPanel with JLabel inside and gave the same problem as the GridBagLayout. It’s the fault of BoxLayout then. I even tried to add glue (vertical Glue) to see if it would help but not change anything. What to do then? Except JList I don’t know any other layout that helps me instead of BoxLayout to produce a vertical list.

  • You will need to set a maximum size for Jpanel, Boxlayout respects the sizes given to the components, when there is nothing reported, the maximum size is Interger_MAX_VALUE for width and height.

  • I get it. I’ll try. Give me an answer and I’ll take it!

  • I’ve already found a solution, it’s pretty silly, but it makes the foundation that I explained make sense

  • If you don’t mind, I’ll convert the comments into the answer, so you don’t have to explain again and avoid fatigue :p

  • Make yourself at home :D

Show 7 more comments

1 answer

1


The BoxLayout will always resize everything within it to occupy as much space as possible up to the maximum size defined by each component within it. Hence the gridbaglayout parameters on JPanel internal do not change the size of the components.

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

You will need to set a maximum size for the JPanel, the BoxLayout respects the sizes given to the components, when there is nothing informed, the maximum size is set to Interger_MAX_VALUE 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 one.

The solution, withdrawn of Soen’s reply, It seems silly but only explores this feature of Boxlayout by setting the maximum size of the Jpanel to the preferred size, which is usually what is needed to compose its content, including edges and internal spacing. Just add the following line at the end of the Jpanel building method JPanelOrderRow and see the magic of layouts happen:

setMaximumSize(getPreferredSize());

Upshot:

inserir a descrição da imagem aqui

Browser other questions tagged

You are not signed in. Login or sign up in order to post.