Search code examples
javaswingjframejbutton

JButton doesn't work at all after i dispose existing frame and sets the new frame(re instantiate another frame)


I made a calculator and to increase its functionality and simplicity i made three frames which support simple , scientific and conversion calculator

calculator works perfect till i use it once but when i change my calculator type from simple to scientific and scientific to conversion and then again to simple calculator , program doesn't do anything at all , jbutton doesn't perform any action even actionPerformed is getting called i checked that by putting println statement in method actionPerformed.

i instantiate my three frames in constructor and i'd made three methods each for calculator type to instantiating and adding buttons and other stuff to JPanels and adding panels to JFrame

//Constructor
public Calculator()
{

    //instantiating buttons
            buttons = new JButton[15];
            optionButtons = new JButton[5];
            scientificOptionButtons = new JButton[20];
            constantButtons = new JButton[5];

            //instantiating calculatorFrames
            simpleCalculatorFrame = new JFrame("Calculator");
            scientificCalculatorFrame = new JFrame("Scientific Calculator");
            convertCalculatorFrame = new JFrame("Conversion Calculator");

    } // end of the constructor

when i choose calculator type from my JMenuItems i dispose the active frame and call other calculatortype methods for creating and adding stuff to panels and setting up frame like

//if statements inside method actionPerformed to check which type of calculator should run
if(event.getSource() == scientificMenuItem)
        {
            if(simpleCalculatorFrame.isActive())
            {
                simpleCalculatorFrame.dispose();
                scientificCalculatorBuilder();
            }
            else if(convertCalculatorFrame.isActive())
            {
                convertCalculatorFrame.dispose();
                scientificCalculatorBuilder();
            }

        }
        else if(event.getSource() == simpleMenuItem)
        {
            if(scientificCalculatorFrame.isActive())
            {
                scientificCalculatorFrame.dispose();
                simpleCalculatorBuilder();
            }
            else if(convertCalculatorFrame.isActive())
            {
                convertCalculatorFrame.dispose();
                simpleCalculatorBuilder();
            }

        }
        else if(event.getSource() == convertMenuItem)
        {
            if(simpleCalculatorFrame.isActive())
            {
                simpleCalculatorFrame.dispose();
                convertCalculatorBuilder();
            }
            else if(scientificCalculatorFrame.isActive())
            {

                scientificCalculatorFrame.dispose();
                convertCalculatorBuilder();
            }

        }
        else if(event.getSource() == exitMenuItem)
        {
            System.exit(0);
        }

everything looks fine just not getting where the problem is

here's code of my methods which instantiates the components

public void simpleCalculatorBuilder()
{


        //instantiating menuBar , fileMenu and menuItems and adding functionality
        menuBar = new JMenuBar();
        fileMenu = new JMenu("File");
        scientificMenuItem = new JMenuItem("Scientific Calculator");
        convertMenuItem = new JMenuItem("Conversion Calculator");
        convertMenuItem.addActionListener(handler);
        scientificMenuItem.addActionListener(handler);
        exitMenuItem = new JMenuItem("Exit");
        exitMenuItem.addActionListener(handler);
        menuBar.add(fileMenu);
        fileMenu.add(scientificMenuItem);
        fileMenu.add(convertMenuItem);
        fileMenu.add(exitMenuItem);

        //instantiating and adding textField appearing at the top of calculator to show ongoing processes and results
        myField = new JTextField();
        myField.setPreferredSize(new Dimension(this.getWidth() , 40));
        myField.setEditable(false);
        simpleCalculatorFrame.add(myField , BorderLayout.NORTH);

        //instantiating panels to hold buttons
        buttonsPanel = new JPanel(new GridLayout(5 , 3 , 3 , 6));
        optionButtonsPanel = new JPanel(new GridLayout(5, 1 , 3 , 3));


        //loop to add buttons to panel , adding eventListeners to buttons , setting background color of buttons
        for(int i = 0 ; i<buttons.length ; i++)
        {
            buttons[i] = new JButton(buttonTitles[i]);
            buttons[i].setBackground(Color.BLACK);
            buttons[i].setForeground(Color.WHITE);
            buttons[i].addActionListener(handler);
            buttons[i].addMouseListener(handler);
            buttonsPanel.add(buttons[i]);
            if(i<5)
            {
                optionButtons[i] = new JButton(optionButtonTitles[i]);
                optionButtons[i].setBackground(Color.BLACK);
                optionButtons[i].setForeground(Color.WHITE);
                optionButtons[i].addActionListener(handler);
                optionButtons[i].addMouseListener(handler);
                optionButtonsPanel.add(optionButtons[i]);
            }
        } 

        //setting background color of panels

        buttonsPanel.setBackground(Color.DARK_GRAY);
        optionButtonsPanel.setBackground(Color.DARK_GRAY);

        //adding items and panels to the frame and setting the simpleCalculatorFrame
        simpleCalculatorFrame.setJMenuBar(menuBar);
        simpleCalculatorFrame.add(buttonsPanel , BorderLayout.CENTER);
        simpleCalculatorFrame.add(optionButtonsPanel , BorderLayout.EAST);
        simpleCalculatorFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        simpleCalculatorFrame.setSize(240 , 270);
        simpleCalculatorFrame.setLocationRelativeTo(null);
        simpleCalculatorFrame.setVisible(true);
        simpleCalculatorFrame.setResizable(false);

} // end of simple calculator builder

public void scientificCalculatorBuilder()
{

    //instantiating menuBar , fileMenu and menuItems and adding functionality
    menuBar = new JMenuBar();
    fileMenu = new JMenu("File");
    simpleMenuItem = new JMenuItem("Simple Calculator");
    simpleMenuItem.addActionListener(handler);
    convertMenuItem = new JMenuItem("Conversion Calculator");
    convertMenuItem.addActionListener(handler);
    exitMenuItem = new JMenuItem("Exit");
    exitMenuItem.addActionListener(handler);
    menuBar.add(fileMenu);
    fileMenu.add(simpleMenuItem);
    fileMenu.add(convertMenuItem);
    fileMenu.add(exitMenuItem);

    //instantiating and adding textField appearing at the top of calculator to show ongoing processes and results
    myField = new JTextField();
    myField.setPreferredSize(new Dimension(this.getWidth() , 40));
    myField.setEditable(false);
    scientificCalculatorFrame.add(myField , BorderLayout.NORTH);

    //instantiating panels to hold buttons
    buttonsPanel = new JPanel(new GridLayout(5 , 3 , 3 , 6));
    optionButtonsPanel = new JPanel(new GridLayout(5, 1 , 3 , 3));
    scientificOptionButtonsPanel = new JPanel(new GridLayout(5 , 4 , 3 , 3));
    constantButtonsPanel = new JPanel(new GridLayout(5, 1 , 3 , 3));
    scientificPanelManager = new JPanel(new GridLayout(1 , 2));



    //loop to add buttons to panel , adding eventListeners to buttons , setting background color of buttons
    for(int i = 0 ; i<scientificOptionButtons.length ; i++)
    {
        if(i<5)
        {
            optionButtons[i] = new JButton(optionButtonTitles[i]);
            optionButtons[i].setBackground(Color.BLACK);
            optionButtons[i].setForeground(Color.WHITE);
            optionButtons[i].addActionListener(handler);
            optionButtons[i].addMouseListener(handler);
            optionButtonsPanel.add(optionButtons[i]);

            constantButtons[i] = new JButton(constantButtonTitles[i]);
            constantButtons[i].setBackground(Color.BLACK);
            constantButtons[i].setForeground(Color.WHITE);
            constantButtons[i].addActionListener(handler);
            constantButtons[i].addMouseListener(handler);
            constantButtonsPanel.add(constantButtons[i]);
        }
        if(i<15)
        {
            buttons[i] = new JButton(buttonTitles[i]);
            buttons[i].setBackground(Color.BLACK);
            buttons[i].setForeground(Color.WHITE);
            buttons[i].addActionListener(handler);
            buttons[i].addMouseListener(handler);
            buttonsPanel.add(buttons[i]);
        }
            scientificOptionButtons[i] = new JButton(scientificOptionButtonTitles[i]);
            scientificOptionButtons[i].setBackground(Color.BLACK);
            scientificOptionButtons[i].setForeground(Color.WHITE);
            scientificOptionButtons[i].addActionListener(handler);
            scientificOptionButtons[i].addMouseListener(handler);
            scientificOptionButtonsPanel.add(scientificOptionButtons[i]);
    }// end of for loop

    //setting background color of panels
    buttonsPanel.setBackground(Color.DARK_GRAY);
    optionButtonsPanel.setBackground(Color.DARK_GRAY);
    scientificOptionButtonsPanel.setBackground(Color.DARK_GRAY);
    constantButtonsPanel.setBackground(Color.DARK_GRAY);

    scientificPanelManager.add(scientificOptionButtonsPanel);
    scientificPanelManager.add(buttonsPanel);
    scientificCalculatorFrame.setJMenuBar(menuBar);
    scientificCalculatorFrame.add(constantButtonsPanel , BorderLayout.WEST);
    scientificCalculatorFrame.add(optionButtonsPanel , BorderLayout.EAST);
    scientificCalculatorFrame.add(scientificPanelManager , BorderLayout.CENTER);
    scientificCalculatorFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    scientificCalculatorFrame.setSize(580 , 300);
    scientificCalculatorFrame.setLocationRelativeTo(null);
    scientificCalculatorFrame.setVisible(true);
    scientificCalculatorFrame.setResizable(false);

} // end of scientificCalculatorBuilder


//method which starts convertCalculatorFrame and initializes frame needs
public void convertCalculatorBuilder()
{

    convertCalculatorTopPanel = new JPanel(new GridLayout(2 , 1 , 0 , 4));
    convertCalculatorCenterPanel = new JPanel(new GridLayout(2 , 2 , 5 , 3));
    convertCalculatorEastPanel = new JPanel(new GridLayout(2 , 1 ,1 , 3));
    convertCalculatorSouthPanel = new JPanel(new GridLayout(1 , 2 , 5 , 2));


    //instantiating menuBar , fileMenu and menuItems and adding functionality
            menuBar = new JMenuBar();
            fileMenu = new JMenu("File");
            simpleMenuItem = new JMenuItem("Simple Calculator");
            simpleMenuItem.addActionListener(handler);
            scientificMenuItem = new JMenuItem("Scientific Calculator");
            scientificMenuItem.addActionListener(handler);
            exitMenuItem = new JMenuItem("Exit");
            exitMenuItem.addActionListener(handler);
            menuBar.add(fileMenu);
            fileMenu.add(simpleMenuItem);
            fileMenu.add(scientificMenuItem);
            fileMenu.add(exitMenuItem);

    typeConvertCalculatorComboBox = new JComboBox<String>();
    typeConvertCalculatorComboBox.setBackground(Color.BLACK);
    typeConvertCalculatorComboBox.setForeground(Color.WHITE);
    typeConvertCalculatorComboBox.setMaximumRowCount(3);

    typeConvertCalculatorComboBox.addItem("Choose type of conversion");
    typeConvertCalculatorComboBox.addItem("Distance Conversion");
    typeConvertCalculatorComboBox.addItem("Memory Conversion");
    typeConvertCalculatorComboBox.addItem("Temperature Conversion");
    typeConvertCalculatorComboBox.addItem("Mass Conversion");

    typeConvertCalculatorComboBox.addActionListener(
            new ActionListener()
            {
                public void actionPerformed(ActionEvent event)
                {
                    if(typeConvertCalculatorComboBox.getSelectedItem() == "Distance Conversion")
                    {
                        fromConvertCalculatorComboBox.setEnabled(true);
                        toConvertCalculatorComboBox.setEnabled(true);

                        fromConvertCalculatorComboBox.removeAllItems();
                        fromConvertCalculatorComboBox.setMaximumRowCount(3);
                        fromConvertCalculatorComboBox.addItem("Centimeter(s)");
                        fromConvertCalculatorComboBox.addItem("Meter(s)");
                        fromConvertCalculatorComboBox.addItem("Kilometer(s)");
                        fromConvertCalculatorComboBox.addItem("Mile(s)");

                        toConvertCalculatorComboBox.removeAllItems();
                        toConvertCalculatorComboBox.setMaximumRowCount(2);
                        toConvertCalculatorComboBox.addItem("Centimeter(s)");
                        toConvertCalculatorComboBox.addItem("Meter(s)");
                        toConvertCalculatorComboBox.addItem("Kilometer(s)");
                        toConvertCalculatorComboBox.addItem("Mile(s)");

                    }
                    else if(typeConvertCalculatorComboBox.getSelectedItem() == "Memory Conversion")
                    {
                        fromConvertCalculatorComboBox.setEnabled(true);
                        toConvertCalculatorComboBox.setEnabled(true);

                        fromConvertCalculatorComboBox.removeAllItems();
                        fromConvertCalculatorComboBox.setMaximumRowCount(3);
                        fromConvertCalculatorComboBox.addItem("Kilobyte(s)");
                        fromConvertCalculatorComboBox.addItem("Megabyte(s)");
                        fromConvertCalculatorComboBox.addItem("Gigabyte(s)");
                        fromConvertCalculatorComboBox.addItem("Terabyte(s)");

                        toConvertCalculatorComboBox.removeAllItems();
                        toConvertCalculatorComboBox.setMaximumRowCount(2);
                        toConvertCalculatorComboBox.addItem("Kilobyte(s)");
                        toConvertCalculatorComboBox.addItem("Megabyte(s)");
                        toConvertCalculatorComboBox.addItem("Gigabyte(s)");
                        toConvertCalculatorComboBox.addItem("Terabyte(s)");
                    }
                    else if(typeConvertCalculatorComboBox.getSelectedItem() == "Temperature Conversion")
                    {
                        fromConvertCalculatorComboBox.setEnabled(true);
                        toConvertCalculatorComboBox.setEnabled(true);

                        fromConvertCalculatorComboBox.removeAllItems();
                        fromConvertCalculatorComboBox.addItem("Centigrade");
                        fromConvertCalculatorComboBox.addItem("Fahrenheit");
                        fromConvertCalculatorComboBox.addItem("Kelvin");

                        toConvertCalculatorComboBox.removeAllItems();
                        toConvertCalculatorComboBox.setMaximumRowCount(2);
                        toConvertCalculatorComboBox.addItem("Centigrade");
                        toConvertCalculatorComboBox.addItem("Fahrenheit");
                        toConvertCalculatorComboBox.addItem("Kelvin");
                    }
                    else if(typeConvertCalculatorComboBox.getSelectedItem() == "Mass Conversion")
                    {
                        fromConvertCalculatorComboBox.setEnabled(true);
                        toConvertCalculatorComboBox.setEnabled(true);

                        fromConvertCalculatorComboBox.removeAllItems();
                        fromConvertCalculatorComboBox.setMaximumRowCount(3);
                        fromConvertCalculatorComboBox.addItem("Milligram(s)");
                        fromConvertCalculatorComboBox.addItem("Pound(s) (lbs)");
                        fromConvertCalculatorComboBox.addItem("Kilogram(s)");

                        toConvertCalculatorComboBox.removeAllItems();
                        toConvertCalculatorComboBox.setMaximumRowCount(2);
                        toConvertCalculatorComboBox.addItem("Milligram(s)");
                        toConvertCalculatorComboBox.addItem("Pound(s) (lbs)");
                        toConvertCalculatorComboBox.addItem("Kilogram(s)");

                    }
                }
            }
            );

    fromConvertCalculatorComboBox = new JComboBox<String>();
    fromConvertCalculatorComboBox.setMaximumRowCount(3);
    fromConvertCalculatorComboBox.setBackground(Color.BLACK);
    fromConvertCalculatorComboBox.setForeground(Color.WHITE);
    fromConvertCalculatorComboBox.setEnabled(false);

    toConvertCalculatorComboBox = new JComboBox<String>();
    toConvertCalculatorComboBox.setMaximumRowCount(2);
    toConvertCalculatorComboBox.setBackground(Color.BLACK);
    toConvertCalculatorComboBox.setForeground(Color.WHITE);
    toConvertCalculatorComboBox.setEnabled(false);


        topConvertCalculatorLabel = new JLabel("What type of conversion you want ?");
        topConvertCalculatorLabel.setForeground(Color.WHITE);
        fromConvertCalculatorLabel = new JLabel("From");
        fromConvertCalculatorLabel.setForeground(Color.WHITE);
        toConvertCalculatorLabel = new JLabel("To");
        toConvertCalculatorLabel.setForeground(Color.WHITE);

        fromConvertCalculatorField = new JTextField();
        fromConvertCalculatorField.setPreferredSize(new Dimension(120 , 2));
        fromConvertCalculatorField.addActionListener(convertHandler);
        ansConvertCalculatorField = new JTextField();
        ansConvertCalculatorField.setEditable(false);

        convertButton = new JButton("Convert");
        convertButton.setBackground(Color.BLACK);
        convertButton.setForeground(Color.WHITE);
        convertButton.addMouseListener(handler);

        convertButton.addActionListener(convertHandler);



        convertCalculatorFrame.setJMenuBar(menuBar);

    //adding components to panel and adding panels to frame
    {
        convertCalculatorTopPanel.add(topConvertCalculatorLabel);
        convertCalculatorTopPanel.add(typeConvertCalculatorComboBox);
        convertCalculatorTopPanel.setBackground(Color.DARK_GRAY);
        convertCalculatorFrame.add(convertCalculatorTopPanel , BorderLayout.NORTH);

        convertCalculatorCenterPanel.add(fromConvertCalculatorLabel);
        convertCalculatorCenterPanel.add(fromConvertCalculatorComboBox);
        convertCalculatorCenterPanel.add(toConvertCalculatorLabel);
        convertCalculatorCenterPanel.add(toConvertCalculatorComboBox);
        convertCalculatorCenterPanel.setBackground(Color.DARK_GRAY);
        convertCalculatorFrame.add(convertCalculatorCenterPanel , BorderLayout.CENTER);

        convertCalculatorEastPanel.add(fromConvertCalculatorField);
        convertCalculatorEastPanel.setBackground(Color.DARK_GRAY);
        convertCalculatorFrame.add(convertCalculatorEastPanel , BorderLayout.EAST);

        convertCalculatorSouthPanel.add(convertButton);
        convertCalculatorSouthPanel.add(ansConvertCalculatorField);
        convertCalculatorSouthPanel.setBackground(Color.DARK_GRAY);
        convertCalculatorFrame.add(convertCalculatorSouthPanel , BorderLayout.SOUTH);

        convertCalculatorFrame.getContentPane().validate();
        convertCalculatorFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        convertCalculatorFrame.setSize(390 , 200);
        convertCalculatorFrame.setLocationRelativeTo(null);
        convertCalculatorFrame.setVisible(true);
        convertCalculatorFrame.setResizable(false);
    }
}//end of convertCalculatorBuilder

i dont have much experience in programming hope you people won't mind helping

here's an MCVE

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

public class Test { 
public static void main(String[] args) {
        Practice application = new Practice();
        application.forFrame1();
}
}

class Practice extends JPanel
{
Handler handler = new Handler();

private JButton[] buttons;
private JButton[] moreButtons;

private JMenuBar menuBar;
private JMenu myMenu;
private JMenuItem firstItem;
private JMenuItem secondItem;

private JFrame frame1;
private JFrame frame2;

private JPanel panel1;
private JPanel panel2;

public Practice()
{
    buttons = new JButton[3];
    moreButtons = new JButton[5];

    frame1 = new JFrame();
    frame2 = new JFrame();
}
public void forFrame1()
{
    menuBar = new JMenuBar();
    myMenu = new JMenu("menu");
    secondItem = new JMenuItem("goto 2nd frame");
    secondItem.addActionListener(handler);
    menuBar.add(myMenu);
    myMenu.add(secondItem);

    frame1.setJMenuBar(menuBar);

    panel1 = new JPanel(new GridLayout(3 , 1));

    for(int i = 0 ; i<buttons.length ; i++)
    {
        buttons[i] = new JButton(""+ i);
        buttons[i].addActionListener(handler);
        panel1.add(buttons[i]);
    }
    frame1.add(panel1);
    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame1.setSize(200 , 200);
    frame1.setVisible(true);
}

public void forFrame2()
{
    menuBar = new JMenuBar();
    myMenu = new JMenu("menu");
    firstItem = new JMenuItem("goto 1st frame");
    firstItem.addActionListener(handler);
    menuBar.add(myMenu);
    myMenu.add(firstItem);
    frame2.setJMenuBar(menuBar);

    panel2 = new JPanel(new GridLayout(1 , 5));
    for(int i = 0 ; i<moreButtons.length ; i++)
    {   
        moreButtons[i] = new JButton(""+ i);
        moreButtons[i].addActionListener(handler);
        panel2.add(moreButtons[i]);
    }
    frame2.add(panel2);
    frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame2.setSize(200 , 200);
    frame2.setVisible(true);
}

private class Handler implements ActionListener
{
    public void actionPerformed(ActionEvent event)
    {
        if(event.getSource() == firstItem)
        {
                frame2.dispose();
                forFrame1();

        }
        else if(event.getSource() == secondItem)
        {
                frame1.dispose();
                forFrame2();    
        }

        for(int i = 0 ; i< moreButtons.length ; i++)
        {
            if(i<buttons.length)
            {
                if(event.getSource() == buttons[i])
        JOptionPane.showMessageDialog(null, "frame1 component working");
            }
            if(event.getSource() == moreButtons[i])
        JOptionPane.showMessageDialog(null, "frame2 components working");
        }
    }
}


}

try using component after changing frame by choosing menuItem


Solution

  • I'm not going to go through all that code without an mcve, but your symptoms tell me the overall problem and the solution: you're re-building an already created JFrame, re-stuffing it with components, without removing old components, without unhooking old listeners, and the components then don't work. This suggests that something in the process of re-building an already built GUI is mucking up your functionality, and if so, the solution is to simply not do this. If you absolutely need to swap JFrames (a very annoying GUI design from a user's perspective by the way), then only create your GUI objects once, but display them multiple times if needed. In other words, call your builder methods just once, perhaps in the constructor, and in your button's ActionListener, don't call the builder methods but rather only the .setVisible(true) and .setVisible(false)


    The bug that is causing your error is that you're adding components to an already filled JFrame and are not packing it, and so the old buttons are shown and are pressed, but their references don't match that of the new buttons. To see this for yourself, add one line to each of the forFrame1() and forFrame2() methods:

        frame1.getContentPane().removeAll(); // ****** add this *****
        frame1.add(panel1);
        frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame1.setSize(200, 200);
        frame1.setVisible(true);
    

    By removing all the old components, you all the new ones to be displayed and to function, and your code will work.

    Having said this, I still feel that your design is off in several ways:

    • Myself, I'd swap JPanels to achieve the desired GUI change, but I wouldn't use a CardLayout since I'd want the container that holds the swapping JPanels to change sizes when the JPanel held has a different preferredSize. This means removing all components, adding new components, and re-packing the GUI.
    • If you must swap windows, then simply swap visibility, and don't re-create your windows as you're doing.
    • Other unrelated issues
      • Let the layout managers and components size themselves by not setting any sizes and by packing the GUI after creation.