1

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);
}
knorberg
  • 462
  • 5
  • 19

3 Answers3

3

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

BackSlash
  • 21,927
  • 22
  • 96
  • 136
  • That didn't work, it just says "thread cannot be applied to given types" and "local variable e is accessed from within inner class; needs to be declared final". Any other ideas? I really appreciate it. – knorberg Jun 20 '13 at 20:03
  • @user2506658 Yes, `Thread` can't use local variables unless they are `final`. So you need to use `final` variables or [Instance variables](http://en.wikipedia.org/wiki/Instance_variable). For the _thread cannot be applied to given types_, what is the full message for the thrown `Exception`? – BackSlash Jun 20 '13 at 20:06
  • @user2506658 See my edit, with changing `public void actionPerformed(ActionEvent e)` to `public void actionPerformed(final ActionEvent e)` the _local variable e is accessed from within inner class; needs to be declared final_ error should disappear – BackSlash Jun 20 '13 at 20:08
  • "method start in class Thread cannot be applied to given types; required: no arguments found: String reason: actual and formal argument lists differ in length" – knorberg Jun 20 '13 at 20:10
  • @user2506658 I tested it and it works, can you please see which line is causing the error and paste here what is written in that line? You can see the exact line in the stack trace – BackSlash Jun 20 '13 at 20:13
  • It says it on `start("yes");` and `start("no");` – knorberg Jun 20 '13 at 20:15
  • @user2506658 It is normal, i forgot that the `Thread` class already has a method called `start` which takes no arguments. You have two solution: the first is the easiest, just change your `start` method name to something else, like `startGame`, and the error will disappear. The other solution is to write, for each `start` method call, `YOURCLASSNAME.this.start("YOURSTRING")`. i.e. if the class that contains the `start` method is named "MyGame", just call `MyGame.this.start("yes")` instead of `start("yes")` – BackSlash Jun 20 '13 at 20:21
  • @user2506658 beware, Swing is a single threaded framework. That is, all creation and modification of the UI is expected to occur within the context of the Event Dispatching Thread (AKA EDT). If you use any kind of thread in a Swing application that ants to interact with the UI in any way, you are required to resync that update with the EDT? See [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for more details, and pay special attention to the section on the SwingWorker – MadProgrammer Jun 20 '13 at 20:52
  • 3
    @BackSlash Beware, this answer may attract downotes as it violates the single thread contract of Swing, leading the OP to a incorrect answer. – MadProgrammer Jun 20 '13 at 20:54
2

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

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
1

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.

resueman
  • 10,572
  • 10
  • 31
  • 45