JButton changes size when pressing toggleButton

693 Views Asked by At

I have a problem with my GUI in that when I press a toggle button belonging to a certain panel, the panels buttons changes size and labels change positions. I've attached some screenshots to show the error in action. I believe its because the buttons are sharing the same panel but I'm unsure whether its fixable so that the buttons size remains static, as do the labels positions.

My code is below (sorry that its quite messy!. I have alot of nested BorderLayout JPanels and this could be where the problem is, but for me it was the easiest way to get the correct layout.

package v2;

import javax.swing.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; 
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;

public class BmrCalcv2 extends JFrame {

    // Frames and main panels
    static JFrame mainFrame;
    static JPanel mainPanel;
    static JPanel combinedGAHWpanel; // combines genderPanel, agePanel, heightPanel, weightPanel - this
                                     // is a BorderLayout, whereas
                                     // gender/agePanel are FlowLayouts.
    static JPanel weightHeightPanel; // Combines weight and height panel into out flowlayout panel, which is then combined into the above borderlayout panel

    // Image components
    static JPanel imgPanel;
    private JLabel imgLabel;

    // Menu-bar components
    static JMenuBar menuBar;
    static JMenu saveMenu, optionMenu, helpMenu;

    // Age components
    static JPanel agePanel;
    private JLabel ageLabel;
    private JLabel yearsLabel;
    private JTextField ageTextField;

    // Gender components
    static JPanel genderPanel;
    private JLabel genderLabel;
    private JRadioButton genderMale;
    private JRadioButton genderFemale;


    // Height components
    static JPanel heightPanel;
    private JLabel heightLabel;
    private JTextField heightCMField;
    private JLabel heightFTLabel;
    private JLabel heightINCHLabel;
    private JTextField heightFTField;
    private JTextField heightINCHField;
    private JToggleButton cmButton;
    private JToggleButton feetButton;


    // Weight components
    static JPanel weightPanel;
    private JLabel weightLabel;
    private JTextField weightField;
    private JToggleButton kgButton;
    private JToggleButton lbButton;


    // TDEE and BMR Components
    static JPanel tdeePanel;
    static JPanel tdeeBMRPanel;
    static JPanel activityLevelPanel;
    static JPanel bmrTDEEValuesPanel;
    static JPanel bmrValuePanel;
    static JPanel tdeeValuePanel;
    private JLabel tdeeQuestionLabel;
    private JLabel activityLevelLabel;
    private JComboBox activityLevelBox;
    private JRadioButton tdeeYes;
    private JRadioButton tdeeNo;
    private JLabel bmrLabel;
    private JLabel tdeeLabel;




    // Default values for gender/weight/height

    String[] activityLevels = {"Sedentary", "Lightly Active", "Moderately Active", "Very Active", "Extra Active"};
    String genderSelection = "M";   
    String weightSelection = "kg";
    String heightSelection = "cm";
    String tdeeSelection = "no";




    public BmrCalcv2(String title) {

        // Main JFrame
        setTitle("BMR/TDEE Calculator");
        mainPanel = new JPanel();

        // All JPanel declarations
        menuBar = new JMenuBar();
        imgPanel = new JPanel();
        agePanel = new JPanel();
        genderPanel = new JPanel();
        heightPanel = new JPanel();
        weightPanel = new JPanel();
        weightHeightPanel = new JPanel(new BorderLayout());
        combinedGAHWpanel = new JPanel(new BorderLayout()); // Create a new panel used to combine
                                                            // genderPanel, agePanel, weightPanel, heightPanel below
        tdeeBMRPanel = new JPanel(new BorderLayout());
        tdeePanel = new JPanel();
        activityLevelPanel = new JPanel();
        bmrTDEEValuesPanel = new JPanel(new BorderLayout());
        bmrValuePanel = new JPanel();
        tdeeValuePanel = new JPanel();



        // Image panel declaration
        imgLabel = new JLabel(new ImageIcon("filesrc//mainlogo.png"));
        imgPanel.add(imgLabel);

        // JPanel layout managers
        agePanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
        genderPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));


        // Menu JComponents
        saveMenu = new JMenu("Save");
        optionMenu = new JMenu("Options");
        helpMenu = new JMenu("Help");
        menuBar.add(saveMenu);
        menuBar.add(optionMenu);
        menuBar.add(helpMenu);

        // Age JComponents
        ageLabel = new JLabel("Age:");
        yearsLabel = new JLabel("<html><i>years</i><html>");
        ageTextField = new JTextField(5);
        agePanel.add(ageLabel);
        agePanel.add(ageTextField);
        agePanel.add(yearsLabel);

        // Gender JComponents
        genderLabel = new JLabel("Gender:");
        genderMale = new JRadioButton("Male", true);
        genderFemale = new JRadioButton("Female");



        genderPanel.add(genderLabel);
        genderPanel.add(genderMale);
        genderPanel.add(genderFemale);


        ButtonGroup genderGroup = new ButtonGroup(); // groups male and female radio buttons together so that only one can be selected
        genderGroup.add(genderMale);
        genderGroup.add(genderFemale);


        genderMale.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
              String genderSelection = "M";   
            } 
        });

        genderFemale.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
              String genderSelection = "F";
            } 
        });

        // Height JComponents
        heightLabel = new JLabel("Height:");
        heightCMField = new JTextField(4);
        heightFTField = new JTextField(3);
        heightFTLabel = new JLabel("ft");
        heightINCHLabel = new JLabel("inch");
        heightINCHField = new JTextField(3);
        cmButton = new JToggleButton("cm", true);
        feetButton = new JToggleButton("feet");
        heightPanel.add(heightLabel);

        ButtonGroup heightGroup = new ButtonGroup();
        heightGroup.add(cmButton);
        heightGroup.add(feetButton);

        heightPanel.add(heightCMField);

        cmButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                  heightSelection = "cm";
                  heightPanel.remove(heightCMField);
                  heightPanel.remove(cmButton);
                  heightPanel.remove(feetButton);
                  heightPanel.remove(heightFTField);
                  heightPanel.remove(heightFTLabel);
                  heightPanel.remove(heightINCHField);
                  heightPanel.remove(heightINCHLabel);
                  heightPanel.add(heightCMField);
                  heightPanel.add(cmButton);
                  heightPanel.add(feetButton);
                  weightHeightPanel.add(heightPanel, BorderLayout.CENTER);
                  combinedGAHWpanel.add(weightHeightPanel, BorderLayout.SOUTH);
                  mainPanel.add(combinedGAHWpanel);
                  add(mainPanel);
                  setVisible(true);
                }
            });

        feetButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                  heightSelection = "feet";
                  heightPanel.remove(heightCMField);
                  heightPanel.remove(cmButton);
                  heightPanel.remove(feetButton);
                  heightPanel.add(heightFTField);
                  heightPanel.add(heightFTLabel);
                  heightPanel.add(heightINCHField);
                  heightPanel.add(heightINCHLabel);
                  heightPanel.add(cmButton);
                  heightPanel.add(feetButton);
                  weightHeightPanel.add(heightPanel, BorderLayout.CENTER);
                  combinedGAHWpanel.add(weightHeightPanel, BorderLayout.SOUTH);
                  mainPanel.add(combinedGAHWpanel);
                  add(mainPanel);
                  setVisible(true);
                }
            });

        heightPanel.add(cmButton);
        heightPanel.add(feetButton);


        // Weight JComponents
        weightLabel = new JLabel("Weight:");
        weightField = new JTextField(4);
        kgButton = new JToggleButton("kg", true);
        lbButton = new JToggleButton("lbs");

        weightPanel.add(weightLabel);
        weightPanel.add(weightField);
        weightPanel.add(kgButton);
        weightPanel.add(lbButton);

        ButtonGroup weightGroup = new ButtonGroup();
        weightGroup.add(kgButton);
        weightGroup.add(lbButton);


        kgButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                weightSelection = "kg"; 
            }
        });

        lbButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                weightSelection = "lb"; 
            }
        });


        // tdee JComponents
        tdeeQuestionLabel = new JLabel("Calculate TDEE Also?");
        tdeeYes = new JRadioButton("Yes");
        tdeeNo = new JRadioButton("No", true);

        ButtonGroup tdeeButton = new ButtonGroup();
        tdeeButton.add(tdeeYes);
        tdeeButton.add(tdeeNo);

        tdeePanel.add(tdeeQuestionLabel);
        tdeePanel.add(tdeeYes);
        tdeePanel.add(tdeeNo);


        // activitylevel JComponents

        activityLevelLabel = new JLabel("Activity Level: ");
        activityLevelBox = new JComboBox(activityLevels);
        activityLevelBox.setSelectedIndex(0);

        activityLevelPanel.add(activityLevelLabel);
        activityLevelPanel.add(activityLevelBox);
        activityLevelBox.setEnabled(false);

        tdeeYes.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                  tdeeSelection = "yes";
                  activityLevelBox.setEnabled(true);
                }
            });

        tdeeNo.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                  tdeeSelection = "no";
                  activityLevelBox.setEnabled(false);
                }
            });



        // tdee and BMR value components

        bmrLabel = new JLabel("BMR: ");
        tdeeLabel = new JLabel("TDEE: ");
        bmrLabel.setFont(new Font("Monotype Corsiva",1,20));
        tdeeLabel.setFont(new Font("Monotype Corsiva",1,20));


        bmrTDEEValuesPanel.add(new JButton("Calculate"), BorderLayout.NORTH);
        bmrTDEEValuesPanel.add(bmrLabel, BorderLayout.CENTER);
        bmrTDEEValuesPanel.add(tdeeLabel, BorderLayout.SOUTH);





        // Adding sub JPanels to main JPanel
        mainPanel.add(imgPanel);

        combinedGAHWpanel.add(agePanel, BorderLayout.NORTH); // Combine genderPanel and agePanel (which are both flowLayouts) into a
                                                             // single BorderLayout panel where agePanel is given the Northern spot and
                                                             // genderPanel is given the center spot in the panel
        weightHeightPanel.add(weightPanel, BorderLayout.NORTH); // Nested borderlayouts, the weightHeightPanel is another borderLayout which is nested
                                                                 // into the southern position of the combinedGAHW border layout.
        weightHeightPanel.add(heightPanel, BorderLayout.CENTER);
        weightHeightPanel.add(tdeeBMRPanel, BorderLayout.SOUTH);




        combinedGAHWpanel.add(genderPanel, BorderLayout.CENTER);
        combinedGAHWpanel.add(weightHeightPanel, BorderLayout.SOUTH);


        mainPanel.add(combinedGAHWpanel);


        // adding to tdeeBMRPanel
        tdeeBMRPanel.add(tdeePanel, BorderLayout.NORTH);
        tdeeBMRPanel.add(activityLevelPanel, BorderLayout.CENTER);


        tdeeBMRPanel.add(bmrTDEEValuesPanel, BorderLayout.SOUTH);


        // Adding main JPanel and menubar to JFrame
        setJMenuBar(menuBar);
        add(mainPanel);
    }


    public static void main(String[] args) {

        BmrCalcv2 gui = new BmrCalcv2("BMR/TDEE Calculator");

        gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gui.setVisible(true);
        gui.setSize(330, 500);
        gui.setResizable(false);

    }
}

enter image description here enter image description here

1

There are 1 best solutions below

17
On

This is combination of changes you are making to the UI (adding/removing labels/fields) and the compound use of a BorderLayout.

You actually don't need to change the label/field when you toggle between "feet" and "CM", as this all the information that the user needs is already available to them (in the form of the buttons).

I'd get rid of the heightFTField, heightINCHField and make this a single field, using the JToggleButton's selected state to determine how you should calculate the values. I'd also get rid of the heightFTLabel, heightINCHLabel labels, they are adding little value to the UI that the toggle buttons are already doing.

Now, having done, you can get rid of the cmButton and feetButton's ActionListeners, as they provide no useful operations.

In future, you may find changing component's visibility state easier.

Based on comments, a basic example

This demonstrates the use of a single field, ButtonGroup to manage the selection of the JToggleButtons and JToggleButton#isSelected to control the logic path

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class JavaApplication63 {

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

    public JavaApplication63() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextField height;
        private JToggleButton cmBtn;
        private JToggleButton feetBtn;

        public TestPane() {
            setLayout(new GridBagLayout());
            height = new JTextField(10);
            cmBtn = new JToggleButton("CM");
            feetBtn = new JToggleButton("Ft");

            ButtonGroup bg = new ButtonGroup();
            bg.add(cmBtn);
            bg.add(feetBtn);
            feetBtn.setSelected(true);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.insets = new Insets(2, 2, 2, 2);

            add(height, gbc);
            gbc.gridx++;
            add(cmBtn, gbc);
            gbc.gridx++;
            add(feetBtn, gbc);

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            JButton calc = new JButton("Calculate");
            calc.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    double valueInCms = 0;
                    if (cmBtn.isSelected()) {
                        valueInCms = Double.parseDouble(height.getText());
                    } else if (feetBtn.isSelected()) {
                        String text = height.getText().replace("'", ".").replace("\"", "");
                        double feet = Double.parseDouble(text);
                        valueInCms = feet * 30.48;
                    }

                    System.out.println("valueInCms = " + valueInCms);
                }
            });
            add(calc, gbc);
        }

    }

}