LayoutManager for different sized components without coding absolute positions

Viewed 53

I'm trying to create some UI but no idea how to use LayoutManger for it.

enter image description here

Like showing in the image Purple color component have fixed width and height but stick to the corners. 8 and 4 have fixed with and variable height, 2 and 6 have fixed height and variable width. the middle component (9) need variable width and height.

These 8 component work like a border and middle one is need to resize according to parent component size. I could do this coding absolute positions using null layout. but I have suggested to not to use null layout.

How could I do this with a Layout manager witch layout I can use for this? Do I need to use more layouts than one?

UPDATE

i have tried something with GridBagLayout as Andrew's suggestion but I still need a little help to understand how it works. Here is my code

 import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GridLayoutTest {
    
    
    
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel jPanel1 = new JPanel();
        jPanel1.setLayout(new GridBagLayout());
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        
        
        
        JButton button;

        GridBagConstraints c = new GridBagConstraints();

        button = new JButton("1");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.gridx = 0;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("2");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("3");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.FIRST_LINE_END;
        c.gridx = 2;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("4");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_START;
        c.weighty = 1.0;
        c.gridx = 0;
        c.gridy = 1;
        jPanel1.add(button, c);

        //Panel
        JPanel panel = new JPanel();
        panel.setBackground(Color.green.darker());
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 0.0;
        //c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 1;
        jPanel1.add(panel, c);

        button = new JButton("5");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_END;
        c.weighty = 1.0;
        c.gridx = 2;
        c.gridy = 1;
        jPanel1.add(button, c);

        button = new JButton("6");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LAST_LINE_START;
        c.gridx = 0;
        c.gridy = 2;
        jPanel1.add(button, c);

        button = new JButton("7");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 2;
        jPanel1.add(button, c);

        button = new JButton("8");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        c.gridx = 2;
        c.gridy = 2;
        jPanel1.add(button, c);
        
        
        frame.add(jPanel1);
        
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setSize(500, 500);
        frame.setVisible(true);
        
    }
   
}

enter image description here

3 Answers

I created the following GUI.

GridBagLayout GUI

I set all six of the GridBagConstraints (anchor, fill, gridx, gridy, weightx, weighty) for each element of the grid. That way, I could more easily keep track of what the values were for each element.

Here's the complete runnable code I used. In other words a minimal, reproducible example.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GridBagLayoutGUI implements Runnable {

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

    @Override
    public void run() {
        JFrame frame = new JFrame("GridBagLayout GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

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

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setPreferredSize(new Dimension(300, 300));

        JButton button;

        GridBagConstraints c = new GridBagConstraints();

        button = new JButton("1");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 0;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("2");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 0.0d;
        c.gridx = 1;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("3");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.FIRST_LINE_END;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 2;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("4");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_START;
        c.weightx = 0.0d;
        c.weighty = 1.0d;
        c.gridx = 0;
        c.gridy = 1;
        panel.add(button, c);

        // Panel
        JPanel innerPanel = new JPanel();
        innerPanel.setBackground(Color.green.darker());
        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 1.0d;
        c.gridx = 1;
        c.gridy = 1;
        panel.add(innerPanel, c);

        button = new JButton("5");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_END;
        c.weightx = 0.0d;
        c.weighty = 1.0d;
        c.gridx = 2;
        c.gridy = 1;
        panel.add(button, c);

        button = new JButton("6");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LAST_LINE_START;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 0;
        c.gridy = 2;
        panel.add(button, c);

        button = new JButton("7");

        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 0.0d;
        c.gridx = 1;
        c.gridy = 2;
        panel.add(button, c);

        button = new JButton("8");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 2;
        c.gridy = 2;
        panel.add(button, c);

        return panel;
    }

}

Another option would be JGoodies FormLayout. I have been using this in combination with JFormDesigner for all my layouting needs since basically forever. It covers 95% percent of my use cases. The remaining 5% is BorderLayout and absolute positioning (null layout).

enter image description here

A common strategy to solve complex computing tasks, is to break them into small, well defined manageable tasks. Divide and conquer. This also applies to gui: you can break the design into small, easy to layout containers. In this case the needed layout can be achieved by using BoxLayout and BorderLayout:

import java.awt.*;
import javax.swing.Box.Filler;
import javax.swing.*;


public class FramedContent extends JPanel{

    private static final int FRAME_WIDTH = 35, CONTENT_SIZE = 300, BORDER_SIZE = 1;
    private static final Color CORNER_COLOR = Color.MAGENTA, RULLER_COLOR = Color.BLUE,
                                CONTENT_COLOR = Color.GREEN, BORDER_COLOR = Color.WHITE;
    FramedContent(){
        setLayout(new BorderLayout());
        add(header(), BorderLayout.NORTH);
        add(center(), BorderLayout.CENTER);
        add(header(), BorderLayout.SOUTH);
    }

    private JPanel header(){
        JPanel hExpandPane = new JPanel();
        hExpandPane.setLayout(new BoxLayout(hExpandPane, BoxLayout.X_AXIS));
        hExpandPane.add(corner());
        hExpandPane.add(hRuller());
        hExpandPane.add(corner());
        return hExpandPane;
    }

    private JComponent corner(){
        Dimension d = new Dimension(FRAME_WIDTH, FRAME_WIDTH);
        Filler filler = new Filler(d, d, d);
        filler.setBackground(CORNER_COLOR);
        filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, BORDER_SIZE));
        filler.setOpaque(true);
        return filler;
    }

    private JComponent hRuller(){
        Dimension d = new Dimension(0,FRAME_WIDTH);
        Filler filler = new Filler(d, d, new Dimension(Short.MAX_VALUE, FRAME_WIDTH));
        filler.setBackground(RULLER_COLOR);;
        filler.setOpaque(true);
        return filler;
    }

    private JPanel center(){
        JPanel vExpandPane = new JPanel();
        vExpandPane.setLayout(new BorderLayout());
        vExpandPane.add(vRuller(), BorderLayout.WEST);
        vExpandPane.add(content(), BorderLayout.CENTER);
        vExpandPane.add(vRuller(), BorderLayout.EAST);
        return vExpandPane;
    }

    private JComponent vRuller(){
        Dimension d = new Dimension(FRAME_WIDTH, 0);
        Filler filler = new Filler(d, d, new Dimension(FRAME_WIDTH, Short.MAX_VALUE));
        filler.setBackground(RULLER_COLOR);
        filler.setOpaque(true);
        return filler;
    }

    private JPanel content(){
        JPanel content = new JPanel(new GridBagLayout());// GridBagLayout used just to center the content
        content.setBackground(CONTENT_COLOR);
        content.add(new JLabel("Your Content Goes Here"));
        content.setPreferredSize(new Dimension(CONTENT_SIZE,CONTENT_SIZE));
        return content;
    }

    public static void createWindow()   {
        JFrame frame = new JFrame("Framed content");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add(new FramedContent());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        createWindow();
    }
}

enter image description here

Related