user3130287
user3130287

Reputation:

Java GridBagLayout JPanels automatically resizing issue?

I need a help with a resizing of Red coloured JPanel. Basically the problem is that I set the grid bag constraints for RED and BLUE JPanel same size and it works perfect, until i add the JLabel, then it just stupidly starts making the RED JPanel Larger size, but it should of been the same size as the BLUE JPanel, 0.05 size it should of stay at. I would be really appreciated if you can help me out, thank you so much in advance :)

http://s30.postimg.org/ag6fy7fg1/Screenshot_32.png

package weatherapp;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class WeatherApp {

    JFrame mainFrame = new JFrame("Weather App");
    Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
    GridBagConstraints gbc = new GridBagConstraints();
    JPanel topMenuBar = new JPanel();
    JPanel weatherInfoMaster = new JPanel();
    JPanel weatherGraphMaster = new JPanel();
    JPanel bottomMenuBar = new JPanel();
    JLabel currentDateLabel = new JLabel(new SimpleDateFormat("dd MMMM yyyy").format(new Date()));

    WeatherApp() {
        constructAppFrame();
        constructTopMenuBar();
    }

    public void constructAppFrame() {
        mainFrame.setSize(540, 960);
        mainFrame.setPreferredSize(new Dimension(540, 960));
        //Terminate the program when the user closes the app.
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.setResizable(false);
        mainFrame.setLocation(screenDimension.width / 2 - mainFrame.getSize().width / 2, screenDimension.height / 2 - mainFrame.getSize().height / 2);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setLayout(new GridBagLayout());

        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1;
        gbc.weighty = 0.05;
        mainFrame.add(topMenuBar, gbc);
        gbc.gridy = 1;
        gbc.weighty = 0.6;
        mainFrame.add(weatherInfoMaster, gbc);
        gbc.gridy = 2;
        gbc.weighty = 0.5;
        mainFrame.add(weatherGraphMaster, gbc);
        gbc.gridy = 3;
        gbc.weighty = 0.05;
        mainFrame.add(bottomMenuBar, gbc);

        mainFrame.pack();
        mainFrame.setVisible(true);
    }

    public void constructTopMenuBar() {
        topMenuBar.setBackground(Color.RED);
        //topMenuBar.setBorder(new EmptyBorder(-20, 20, -20, 20));
        topMenuBar.setLayout(new BoxLayout(topMenuBar, BoxLayout.X_AXIS));
        currentDateLabel.setForeground(Color.WHITE);
        currentDateLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 20));
        currentDateLabel.setBackground(Color.BLUE);
        currentDateLabel.setOpaque(true);

        topMenuBar.add(currentDateLabel);

        weatherInfoMaster.setBackground(Color.CYAN);
        weatherGraphMaster.setBackground(Color.GREEN);
        bottomMenuBar.setBackground(Color.BLUE);
    }

    public static void main(String[] args) {
        //Create the frame on the event dispacthing thread.
        SwingUtilities.invokeLater(() -> {
            new WeatherApp();
        });
    }
}

Upvotes: 1

Views: 1357

Answers (1)

camickr
camickr

Reputation: 324098

//mainFrame.setLocation(screenDimension.width / 2 - mainFrame.getSize().width / 2, screenDimension.height / 2 - mainFrame.getSize().height / 2);
mainFrame.setLocationRelativeTo(null);

The first statement is not needed, since the setLocationRelativeTo(...) will reset the location.

constructAppFrame();
constructTopMenuBar();

Don't add components to the frame AFTER the frame is visible. The order of the two statements should be reversed.

it just stupidly starts making the RED JPanel Larger size, but it should of been the same size as the BLUE JPanel, 0.05 size it should of stay at.

It is not stupid. It is well defined behaviour of the layout manager. Every layout manager has it own rules to follow. The GridBagLayout works on the "preferred size" of components. When no components are added to the panel the preferred size is (10, 10) because a JPanel uses a FlowLayout by default and the default gap before/after components is 5 pixels.

So when extra space is available the GridBagLayout allocates the space based on the preferred size which results in the red getting more space.

As a quick hack (after following my other suggestions from above) you can do:

bottomMenuBar.setPreferredSize( topMenuBar.getPreferredSize() );
mainFrame.add(bottomMenuBar, gbc);

Now the sizes will be the same because the preferred size is also the same. This proof of concept is not really a good solution because the preferred size of the blue panel becomes fixed even if you change the red panel.

Maybe a better solution is to use the Relative Layout. This layout will size the components based on the space available in frame, not the preferred size, so if the red/blue panels have the same relative size they should be the same size even as components are added.

Upvotes: 3

Related Questions