Search code examples
javaswingjframejwindow

Resizing FlowLayout panels


I'm trying to create a JPanel that uses the FlowLayout. This panel is placed inside of a container using BorderLayout. This container is then added to a card using CardLayout. I would like the panel using FLowLayout ot be a small box in the bottom left corner of the BorderLayout panel. How would I do this? I've used settingsPanel.setPreferredSize(new Dimension(10, 425)); but the width still spans across the whole panel no matter what size I set, although the height changes. How would I get the width to change?

Code:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class Main {
    //Settings Panel variables
    JLabel settingsTitle = new JLabel("Settings");

    public Main()
    {
        JPanel mainCard = new JPanel(new BorderLayout(8,8));
        JPanel settingsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        settingsTitle.setFont(new Font("TimesRoman", Font.PLAIN, 35));
        settingsPanel.add(settingsTitle);

        final CardLayout layout = new CardLayout();
        final JPanel cards = new JPanel(layout);
        cards.add(mainCard, "2");

        mainCard.add(settingsPanel, BorderLayout.SOUTH);

        settingsPanel.setPreferredSize(new Dimension(10, 425));
        settingsPanel.setBorder(BorderFactory.createLineBorder(Color.black));

        layout.show(cards, "1");

        JFrame window = new JFrame("Test");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.getContentPane().add(cards);
        window.setSize(1280, 720);
        window.setLocationRelativeTo(null);
        window.setResizable(false);
        window.setVisible(true);

    }

    public static void main(String[] args)
    {

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Main();
            }
        });

    }
}

Example:

enter image description here


Solution

  • So here's your code changing the BorderLayout with GridBagLayout. The core idea of the GridBagLayout is that you'll have a grid with several rows and columns (of different sizes) and you can place components in each cell. The neat thing about it is that it's very powerful: when you place a component in a cell you can customize the following:

    • How many cells can it span through (vertically, horizontally or both) (gridwidth/gridheight)
    • Where in the cell to put it on: center, top-left, bottom-right... (anchor)
    • The weight of each row/column, this is how much space, proportionally, do they eat when resizing/distribuiting the window. (weightx, weighty)
    • Whether they have to occupy the maximum or the minimum space necessary. (fill)

    Among other things. The last point was your problem here, BorderLayout was forcing your panel to expand as much as it could. In my code I used fill = NONE and set it at the anchor = LAST_LINE_START so it stays at the bottom left and doesn't expand.

    You can play with these parameters, all the info is in the tutorial. The key to all of it is to know how is your grid. In this example it's very simple it's just a 1x1. But look at the tutorial: those images with a grid painted in red over them, that's what you have to have in your mind. Other than that and knowing all the variables the only tricky thing is how weights work.

        import java.awt.BorderLayout;
        import java.awt.CardLayout;
        import java.awt.Color;
        import java.awt.Dimension;
        import java.awt.FlowLayout;
        import java.awt.Font;
        import java.awt.GridBagConstraints;
        import java.awt.GridBagLayout;
    
        import javax.swing.BorderFactory;
        import javax.swing.BoxLayout;
        import javax.swing.JFrame;
        import javax.swing.JLabel;
        import javax.swing.JPanel;
        import javax.swing.SwingUtilities;    
        public class Main {
        //Settings Panel variables
        JLabel settingsTitle = new JLabel("Settings");
    
        public Main()
        {
            JPanel mainCard = new JPanel(new GridBagLayout());
            JPanel settingsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
            settingsTitle.setFont(new Font("TimesRoman", Font.PLAIN, 35));
            settingsPanel.add(settingsTitle);
    
            final CardLayout layout = new CardLayout();
            final JPanel cards = new JPanel(layout);
            cards.add(mainCard, "2");
    
            GridBagConstraints c = new GridBagConstraints();
            c.gridx = 0;
            c.gridy = 0;
            c.weightx = 1.0;
            c.weighty = 1.0;
            c.anchor = GridBagConstraints.LAST_LINE_START;
            c.fill = GridBagConstraints.NONE; //uneeded line because it's the default value, but it has to be NONE
    
            mainCard.add(settingsPanel, c);
    
           // settingsPanel.setPreferredSize(new Dimension(300, 425)); //the components inside settingsPanel will set its side
            settingsPanel.setBorder(BorderFactory.createLineBorder(Color.black));
    
            layout.show(cards, "1");
    
            JFrame window = new JFrame("Test");
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.getContentPane().add(cards);
            window.setSize(1280, 720); ///replace with window.pack()
            window.setLocationRelativeTo(null);
            window.setResizable(false);
            window.setVisible(true);
    
        }
    
        public static void main(String[] args)
        {
    
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Main();
                }
            });
    
        }
    }