为什么我的Swing应用程序冻结?

时间:2013-06-20 19:45:48

标签: java swing user-interface jbutton infinite-loop

基本上,每次点击我的一个JButton时,它都会锁定。我一直在环顾四周,发现它可能是因为无限循环,但我无法在任何地方看到它。

一双新鲜的眼睛会非常方便!

无论如何,这里是声明的JButtons:

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

这是我的main()方法:

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();
}

这是Start()方法:

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;
            }
}

这是JButton监听器的actionPerformed()方法:

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";
        }
    }
}

我认为它以某种方式连接到JButtons。

如果我需要显示更多代码,请告诉我。

无论如何,感谢任何和所有帮助!

感谢您的帮助和时间!

编辑:对不起,我忘了向JBUttons显示听众:

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

编辑:此外,这是Game()方法:

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

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

    choiceRerollDice();
}

rollDice#方法:

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);
}

3 个答案:

答案 0 :(得分:3)

问题是你的ActionListener在不使用新线程的情况下完成所有操作。这意味着您正在冻结UI线程,这基本上会阻止UI刷新。

您可以在Thread方法中使用actionPerformed

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();

}

使用线程将阻止UI冻结

<强>更新

正如MadProgrammer所说,在这种情况下,最好使用SwingWorker而不是线程

答案 1 :(得分:2)

我怀疑choiceRerollDice正在使用扫描程序来读取用户的输入,这会阻止事件调度线程,从而阻止重新绘制它。

您正在将CLI范例与GUI范例混合在一起,这又引出了一个问题,原因是什么?

使用图形界面时不应使用CLI样式输入(即Scanner),而应使用可用的图形控件,例如按钮或文本字段

答案 2 :(得分:1)

看起来你永远不会将任何监听器附加到按钮上,而是尝试从System.in读取。如果这是真的,那么程序将挂起,等待来自System.in的输入。

而不是

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

使用

按钮上的actionListeners
textYes.addActionListener(/*Your Action Listener*/);
...

编辑 - 即使附加了ActionListeners,它也会挂在扫描仪行上,试图从输入流中读取。删除这些行应该修复它。