knorberg
knorberg

Reputation: 462

Why is my Swing application freezing?

Basically, every time I click on one of my JButtons, it just locks up. I have been looking around and found out that it may be because of an infinite loop, but I cannot see one anywhere.

A fresh pair of eyes would come in very handy!

Anyways, here are the JButtons being declared:

public static JButton textYes = new JButton("Yes");
public static JButton textNo = new JButton("No");

Here is my main() method:

public static void main(String[] args) throws IOException {
    Greed gui = new Greed();
    gui.launchFrame();
    redirectSystemStreams();

    Container contentPane = f.getContentPane();
    contentPane.add(new Greed());

    Scanner is = new Scanner(System.in);
    System.out.println("Welcome to Greed...");
        //do {
    System.out.println("Would you like to play? (yes/no)");
    area = "menu";
    menu = is.next();
}

Here is the Start() method:

public static void start(String menu) {
            switch (menu) {
                case "yes":
                    jTextArea1.setText(null);
                    diceOne = 0;
                    diceTwo = 0;
                    diceThree = 0;
                    diceFour = 0;
                    diceFive = 0;
                    System.out.println("Rolling...");
                    Game();

                    break;
                case "no":
                    System.out.println("Goodbye...");
                    System.exit(0);

                    break;
                default:
                    invalidInput();

                    break;
            }
}

And here is the actionPerformed() method with the JButton listeners:

public void actionPerformed(ActionEvent e) {
    //jTextArea1.setText(null);
    if (box1.isSelected()) {
        System.out.println("1 is selected");
        willRerollDiceOne = true;
    }
    else {
        //System.out.println("1 not selected");
        willRerollDiceOne = false;
    }
    if (box2.isSelected()) {
        System.out.println("2 is selected");
        willRerollDiceTwo = true;
    }
    else {
        //System.out.println("2 not selected");
        willRerollDiceTwo = false;
    }
    if (box3.isSelected()) {
        System.out.println("3 is selected");
        willRerollDiceThree = true;
    }
    else {
        //System.out.println("3 not selected");
        willRerollDiceThree = false;
    }
    if (box4.isSelected()) {
        System.out.println("4 is selected");
        willRerollDiceFour = true;
    }
    else {
        //System.out.println("4 not selected");
        willRerollDiceFour = false;
    }
    if (box5.isSelected()) {
        System.out.println("5 is selected");
        willRerollDiceFive = true;
    }
    else {
        //System.out.println("5 not selected");
        willRerollDiceFive = false;
    }

    if ("menu".equals(area)) {
        if(e.getSource() == textYes){
            start("yes");
        }
        if(e.getSource() == textNo){
            start("no");
        }
    }
    if ("choiceReroll".equals(area)) {
        if(e.getSource() == textYes){
            choiceReroll = "yes";
        }
        if(e.getSource() == textNo){
            choiceReroll = "no";
        }
    }
}

I'm thinking it is somehow connected to the JButtons.

Let me know if I need to display more code.

Anyways, any and all help is appreciated!

Thank you for your help and for your time!

EDIT: Sorry about that, I forgot to show the listeners being attached to the JBUttons:

textYes.addActionListener(this);
textNo.addActionListener(this);

EDIT: Also, here is the Game() method:

public static void Game() {
    rollDiceOne();
    rollDiceTwo();
    rollDiceThree();
    rollDiceFour();
    rollDiceFive();

    displayDiceValues();
    f.validate();
    f.repaint();

    choiceRerollDice();
}

And the rollDice# methods:

public static void rollDiceOne() {
    diceOne = 1 + (int)(Math.random()*6);
}
public static void rollDiceTwo() {
    diceTwo = 1 + (int)(Math.random()*6);
}
public static void rollDiceThree() {
    diceThree = 1 + (int)(Math.random()*6);
}
public static void rollDiceFour() {
    diceFour = 1 + (int)(Math.random()*6);
}
public static void rollDiceFive() {
    diceFive = 1 + (int)(Math.random()*6);
}

Upvotes: 1

Views: 293

Answers (3)

BackSlash
BackSlash

Reputation: 22243

The problem is that your ActionListener does all operations without using a new thread. This means that you are freezing the UI thread, which basically stops the UI from refreshing.

What you can do is to use a Thread in the actionPerformed method.

public void actionPerformed(final ActionEvent e) {
    Thread t = new Thread() {
        public void run() {
            //jTextArea1.setText(null);
            if (box1.isSelected()) {
                System.out.println("1 is selected");
                willRerollDiceOne = true;
            }
            else {
                //System.out.println("1 not selected");
                willRerollDiceOne = false;
            }
            if (box2.isSelected()) {
                System.out.println("2 is selected");
                willRerollDiceTwo = true;
            }
            else {
                //System.out.println("2 not selected");
                willRerollDiceTwo = false;
            }
            if (box3.isSelected()) {
                System.out.println("3 is selected");
                willRerollDiceThree = true;
            }
            else {
                //System.out.println("3 not selected");
                willRerollDiceThree = false;
            }
            if (box4.isSelected()) {
                System.out.println("4 is selected");
                willRerollDiceFour = true;
            }
            else {
                //System.out.println("4 not selected");
                willRerollDiceFour = false;
            }
            if (box5.isSelected()) {
                System.out.println("5 is selected");
                willRerollDiceFive = true;
            }
            else {
                //System.out.println("5 not selected");
                willRerollDiceFive = false;
            }

            if ("menu".equals(area)) {
                if(e.getSource() == textYes){
                    start("yes");
                }
                if(e.getSource() == textNo){
                    start("no");
                }
            }
            if ("choiceReroll".equals(area)) {
                if(e.getSource() == textYes){
                    choiceReroll = "yes";
                }
                if(e.getSource() == textNo){
                    choiceReroll = "no";
                }
            }
        }
    };
    t.start();

}

Using a thread will prevent UI freeze

UPDATE

As MadProgrammer said, in this case it is better to use a SwingWorker instead of a Thread

Upvotes: 3

MadProgrammer
MadProgrammer

Reputation: 347334

I suspect that the choiceRerollDice is using a scanner to read input from the user, which is blocking the Event Dispatching Thread, preventing it from being repainted.

You are mixing a CLI paradigm with a GUI paradigm, which raises the question, again, why?

You should not be using a CLI style input (ie Scanner) when using a graphical interface, instead you should be using the graphical controls available to you, like buttons or text fields for example

Upvotes: 2

resueman
resueman

Reputation: 10623

It looks like you're never attaching any listeners to the buttons, but instead trying to read from System.in. If that's true, then the program will hang, waiting for input from System.in.

Instead of having

Scanner is = new Scanner(System.in);
...
area = "menu";
menu = is.next();

Use actionListeners on the buttons, with

textYes.addActionListener(/*Your Action Listener*/);
...

Edit - Even with the ActionListeners attached, it's going to hang on the Scanner lines, trying to read from the input stream. Removing those lines should fix it.

Upvotes: 1

Related Questions