Java JPanel GroupLayout formatting problem

48 Views Asked by At

I am trying to layout my JPanel such that:

  • The information label is at the top,
  • The text area is directly below, this and the info label go across (horizontally) the entire panel,
  • Below the text from left to right (equally spaced) are the config, save and then clear buttons,
  • Below those is the success/failure label (central, under the save button) and the home button (right, under the clear button).

I have tried many combinations and used other stack answers but cannot get it right, something about group layout I can't get my head around!

import javax.swing.*;

public class JFrameTest {
    private static JFrame mainApp;
    private static JPanel mainPanel;

public JFrameTest() {
        mainApp = new JFrame("Application");
        mainApp.setSize(640, 480);
        mainApp.setLocationRelativeTo(null);
        mainApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainApp.add(mainPanel());
        mainApp.setVisible(true);
    }

    private JPanel mainPanel() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        mainPanel= new JPanel();
        mainPanel.setSize(600,450);
        Container container = mainApp.getContentPane();
        
        JLabel labelInfo = new JLabel("add necessary information here");
        JLabel labelSOrF = new JLabel("Success/Failure");
        //    labelSOrF.setVisible(false);

        JTextArea textArea = new JTextArea();

        JButton configButton= new JButton("config");
        JButton saveButton= new JButton("save");
        JButton clearButton= new JButton("clear");
        JButton homeButton= new JButton("Home");

        GroupLayout layout = new GroupLayout(container);
        container.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);

        layout.setHorizontalGroup(
                layout.createSequentialGroup()
                    .addGroup(layout.createParallelGroup()
                            .addComponent(configButton)
                    .addGroup(layout.createParallelGroup()
                            .addComponent(saveButton)
                            .addComponent(labelSOrF, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createParallelGroup()
                            .addComponent(clearButton)
                            .addComponent(homeButton)
                    .addComponent(labelInfo)
                    .addComponent(textArea, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    )))
        );
        layout.setVerticalGroup(
                layout.createSequentialGroup()
                    .addComponent(labelInfo)
                    .addComponent(textArea, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createParallelGroup()
                            .addGroup(layout.createSequentialGroup()
                                    .addComponent(configButton)
                                    .addComponent(saveButton)
                                    .addComponent(buttonClear))
                    .addGroup(layout.createParallelGroup()
                            .addComponent(labelSOrF, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(homeButton)))
        );

edit - added code

1

There are 1 best solutions below

0
Gilbert Le Blanc On

Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.

GroupLayout was designed for GUI builders. No human being will deliberately use a GroupLayout. It's too hard to understand and as you've discovered, maintain.

Here's a GUI that meets your requirements.

Application

Swing was designed to be constructed from the inside out. You layout the Swing components and let the JPanels and the JFrame size themselves. You don't start with the JFrame and fit all the Swing components.

All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.

I created a main JPanel with three subordinate JPanels. To construct a complex GUI, you nest simple JPanels.

I added the Swing components to each JPanel in column, row order. That helps me to organize the code and makes it easier for readers of your code to understand the code.

Here's the complete runnable code.

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class JFrameTest implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new JFrameTest());
    }

    @Override
    public void run() {
        JFrame mainApp = new JFrame("Application");
        mainApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        mainApp.add(createMainPanel(), BorderLayout.CENTER);

        mainApp.pack();
        mainApp.setLocationRelativeTo(null);
        mainApp.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
        
        panel.add(createTitlePanel());
        panel.add(createTextAreaPanel());
        panel.add(createButtonPanel());

        return panel;
    }

    private JPanel createTitlePanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));

        JLabel labelInfo = new JLabel("add necessary information here");
        panel.add(labelInfo);

        return panel;
    }

    private JPanel createTextAreaPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));

        JTextArea textArea = new JTextArea(5, 40);
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        panel.add(scrollPane);

        return panel;
    }

    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new GridLayout(0, 3, 20, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));

        JButton configButton = new JButton("config");
        panel.add(configButton);

        JButton saveButton = new JButton("save");
        panel.add(saveButton);

        JButton clearButton = new JButton("clear");
        panel.add(clearButton);
        
        JLabel dummy = new JLabel(" ");
        panel.add(dummy);

        JLabel labelSOrF = new JLabel("Success/Failure");
        panel.add(labelSOrF);

        JButton homeButton = new JButton("Home");
        panel.add(homeButton);

        return panel;
    }

}