Search code examples
javaswingstack-overflow

Came across an issue while creating a difficulty selector


OK so if I select hard and then I select easy it gives me this exception in thread

AWT-EventQueue-0" java.lang.StackOverflowError

I only wanted to see how it works if you have any tips / ideas it would be grateful.

Here is the code:

import java.awt.Component;
import java.awt.Container;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.JCheckBox;
import javax.swing.JFrame;


public class Difficulty extends JFrame {

/**
 * 
 */
private static JCheckBox easy;
private static JCheckBox hard;
private static Container pane;
private Handeler handeler;
private static final long serialVersionUID = 1L;

public Difficulty() {
    super("Select a Difficulty");
    pane = new Container();
    getContentPane().add(pane);
    pane.add(Easy());
    pane.add(Hard());
}

public Component Hard() {
    handeler = new Handeler();
    hard = new JCheckBox("Hard");
    hard.setBounds(60, 40, 60, 50);
    hard.setVisible(true);
    hard.addItemListener(handeler);
    return hard;
}

private Component Easy() {
    handeler = new Handeler();
    easy = new JCheckBox("Easy");
    easy.setBounds(60, 0, 60, 50);
    easy.setVisible(true);
    easy.addItemListener(handeler);
    return easy;
}

public static void main(String[] args) {
    Difficulty gui = new Difficulty();
    gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    gui.setLocationRelativeTo(null);
    gui.setSize(200, 200);
    gui.setVisible(true);
    gui.setResizable(false);

}

private class Handeler implements ItemListener {

    @Override
    public void itemStateChanged(ItemEvent item) {

        if(item.getSource() == easy){
            for(int x = 0; x < 1; x++){
                if(hard.isSelected()){
                    hard.setSelected(false);
                    easy.setSelected(true);
                }else {easy.setSelected(true);}
            }

            }else if(item.getSource() == hard){
                for(int x = 0; x < 1; x++){
                if(easy.isSelected()){
                    easy.setSelected(false);
                    hard.setSelected(true);
                }else{hard.setSelected(true);}
                }
            }
        }
}

Solution

  • Yes you have an infinite loop. When you either check box you then set the set of the other check box which causes the ItemListener for that check box to fire and the whole cycle keep repeating itself.

    You should not be using check boxes for this type of requirement. Instead you should be using JRadioButtons with a ButtonGroup. Then when you select a radio button the other button will automatically be unselected for you. You don't even need to write a listener. Read the section from the Swing tutorial on How to Use RadioButtons for more information and working examples.

    Also, as a side note, why would you ever write code with a loop like that in your ItemListener? The event is only generated for the button you click so you only ever need to check the state that check box. You don't need to change the state of the check box you clicked, that is part of the built in functionality of clicking on the check box.

    Finally, don't use setBounds(...). That code does nothing. It is the job of the layout manager to set the size and location of the component.