Distribution of components in GroupLayout

1

The example below has a GroupLayout that contains two elements, a custom search and filter bar ( JPanelSearchAndFilter ) and a JScrollPane .

When it is run and then the window is maximized you can see that these two elements are evenly distributed on the screen.

When you select any item in the combo box, the screen fills with lines of text and the search and filter bar becomes smaller on the screen, making room for lines of text.

I'd like to know how to make this toolbar smaller in size from the start of execution. Preferably without using a BorderLayout for this.

I thought about setting the size of JScrollPane or filling it with invisible items, but this seems to me to be gambiarra. I believe a solution is possible using layout managers .

GroupPanel.java

import java.awt.EventQueue;
import java.awt.Font;

import javax.swing.BoxLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class GroupPanel extends JPanel implements Listener   {

    private static final long serialVersionUID = 1L;

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

    public GroupPanel() {

        javax.swing.GroupLayout jPanelMainLayout = new javax.swing.GroupLayout(this);

        jPanelMainLayout.setHorizontalGroup(jPanelMainLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(jPanelMainLayout.createSequentialGroup()
                        .addGroup(jPanelMainLayout.createParallelGroup(Alignment.LEADING)
                                .addComponent(jPanelSearchAndFilter)
                                .addComponent(jScrollPaneOrders))
                        ));

        jPanelMainLayout.setVerticalGroup(jPanelMainLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(jPanelMainLayout.createSequentialGroup().addGroup(
                        jPanelMainLayout.createParallelGroup(Alignment.LEADING)
                        .addGroup(jPanelMainLayout.createSequentialGroup()
                                .addComponent(jPanelSearchAndFilter)
                                .addComponent(jScrollPaneOrders)))));

        this.setLayout(jPanelMainLayout);

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

        jPanelSearchAndFilter.setListener(this);
    }

    private static void display() {
        JFrame f = new JFrame("GroupPanel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS));
        f.add(new GroupPanel());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

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

            @Override
            public void run() {
                display();
            }
        });
    }

    @Override
    public void onEvent(String event) {
        for (int i = 1; i <= 10; i++) {
            JLabel label = new JLabel(event + " " + i);
            label.setFont(new Font("Tahoma", Font.BOLD, 60));
            jPanelListaOrders.add(label);
        }

        revalidate();
        repaint();
    }
}

JPanelSearchAndFilter.java

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Objects;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class JPanelSearchAndFilter extends JPanel {

    private static final String [] ORDER_STATUSES = {
            "Todos",
            "Novos",
            "Confirmados",
            "Prontos/Enviados",
            "Entregues",
            "Cancelados"
            };

    private Listener listener = null;

    public JPanelSearchAndFilter() {

        setForeground(Color.GRAY);
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

        setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        searchField = new JTextField("Pesquisar");
        searchField.setForeground(Color.GRAY);
        searchField.setFont(new Font("Tahoma", Font.PLAIN, 15));
        searchField.setToolTipText("Pesquisar");
        add(searchField);
        searchField.setColumns(10);

        // Cria um espaço vazio de tamanho fixo entre searchField e filterComboBox.
        add(Box.createRigidArea(new Dimension(20, 0)));

        ComboBoxModel<String> filterComboModel = new DefaultComboBoxModel<>(ORDER_STATUSES);
        JComboBox<String> filterComboBox = new JComboBox<>(filterComboModel);
        filterComboBox.setFont(new Font("Tahoma", Font.PLAIN, 15));
        filterComboBox.setSelectedIndex(0);

        filterComboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent itemEvent) {
                JPanelSearchAndFilter.this.listener.onEvent((String)itemEvent.getItem());
            }
        });

        add(filterComboBox);
    }

    public void setListener(Listener listener) {
        this.listener = listener;
    }

    private static final long serialVersionUID = 1L;
    private JTextField searchField;
}

Listener.java

public interface Listener {
    public void onEvent(String event);
}
    
asked by anonymous 22.11.2018 / 13:41

1 answer

2

The layout manager you are using ( GroupLayout ) it works with relative values, and you end up mixing another layout ( BoxLayout ) on top that also works with relative values to define the distribution of the components on the screen, but the former ends up prevailing. The problem is that by revalidating the panel, it understands that it needs to have more space for the list and reduces the size of the other panel with the text field.

Although it is a very robust layout manager, Grouplayout is extremely complex to use, so much so that it is usually only used by IDE generation screenshots like netbeans.

The solution to the problem I encountered was to completely remove GroupLayout and use BorderLayout , which in spite of also working with relative values, it better defines the distribution of the components on the screen, distributing in 5 fixed regions. Since you want the search pane to be at the top and the list pane at the back of the search pane, just set it as your class GroupPanel :

    this.setLayout(new BorderLayout());

    this.add(jPanelSearchAndFilter, BorderLayout.NORTH);
    this.add(jScrollPaneOrders, BorderLayout.CENTER);

If no other region is defined, JSCrollPane will occupy all other regions of Borderlayout , from the defined region.

Another detail I've also modified is repaint() , since, as this answer , the same is already invoked internally when you run revalidate() to redraw the screen.

The code looks like this:

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

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

public class GroupPanel extends JPanel implements Listener {

    private static final long serialVersionUID = 1L;

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

    public GroupPanel() {

        this.setLayout(new BorderLayout());

        this.add(jPanelSearchAndFilter, BorderLayout.NORTH);
        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));

        jPanelSearchAndFilter.setListener(this);
    }

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

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

    @Override
    public void onEvent(String event) {
        for (int i = 1; i <= 10; i++) {
            JLabel label = new JLabel(event + " " + i);
            label.setFont(new Font("Tahoma", Font.BOLD, 60));
            jPanelListaOrders.add(label);
        }

        revalidate();
    }
}
    
22.11.2018 / 14:13