简体   繁体   English

java程序卡在while循环中

[英]java program stuck in while loop

I'm writing a text based adventure game and I ran into a problem. 我正在写一个基于文本的冒险游戏,我遇到了一个问题。 I'm porting it over from terminal to JFrame GUI and I need it to wait for user input before proceeding. 我正在将它从终端移植到JFrame GUI,我需要它在继续之前等待用户输入。 I set up a system where there is a boolean variable called buttonPressed which starts out as false. 我建立了一个系统,其中有一个名为buttonPressed的布尔变量,它以false开头。 When the submit text button is pressed it changes it to true. 按下提交文本按钮后,将其更改为true。 There is a while loop that waits for the button to become true before it allows the program to continue, essentially pausing the program until the user submits input. 有一个while循环在允许程序继续之前等待按钮变为true,基本上暂停程序直到用户提交输入。 The problem is this only works when I have inside the while loop a system.out.println line written in. Otherwise it doesn't continue after I click the button. 问题是这只有当我在while循环中写入一个system.out.println行时才有效。否则它在我点击按钮后不会继续。 What's the problem? 有什么问题?

public class event implements ActionListener{
    public void actionPerformed(ActionEvent e){
        moves += 1;
        movesLabel.setText("Moves: " + moves);

        buttonPressed = true;

        try{
            input = (String)(textfield.getText());
            textfield.setText("");

        }catch(Exception ex){
            textfield.setText("Error");
        }
    }
}


public static void main (String args[]) {
    Main gui = new Main();
    gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    gui.setVisible(true);
    gui.setSize(650, 350);
    gui.setTitle("Sprinkles Text Adventure");

    setInventory();

    textArea.setText(textDisplay("Welcome Adventurer!"));
    textArea.setText(textDisplay("What is thy name: "));

    while(!buttonPressed){
      // this only works when I have system.out.println("something") written in
    }

    buttonPressed = false;

    textArea.setText(textDisplay(input));

    if ("alice".equals(input)||"Alice".equals(input)){
        textArea.setText(textDisplay("Stop toking the magical pipe, "));
        textArea.setText(textDisplay("you aren't alice and this isn't wonderland"));
        textArea.setText(textDisplay("Now down the rabbit hole you go!"));
    }
    else if ("l3ikezI".equals(input)||"l3ikezi".equals(input)){
        System.out.println("Magic and Technology flows through your veins");
        System.out.println("Welcome back, Master");
        for(int j = 0; j<14; j++){
            Chest[j]=1;
        }
    }
    else{
        System.out.println("Enter " + input + " and good luck!\n\n");
    }

Im no java expert but... 我没有java专家,但......
It looks like you are not giving your gui thread time to do anything, since you are busy waiting for your boolean to change. 看起来你没有给你的gui线程时间做任何事情,因为你正忙着等待你的布尔值改变。 To solve this you should probably use a semaphore . 要解决这个问题,你应该使用信号量 Or, the easier (dirty) solution, call a sleep() in your while loop. 或者,更容易(脏)的解决方案,在while循环中调用sleep() For java specific things, look at this question. 对于java特定的东西,请看这个问题。

On second thought, I found that java has a volatile keyword. 第二个想法,我发现java有一个volatile关键字。 I don't know if buttonPressed is declared volatile , but if it is not, the compiler might decide that, since the while-loop is empty, its value is never going to changes, and replaces it by while(true) as an optimisation. 我不知道buttonPressed是否被声明为volatile ,但如果不是,编译器可能会决定,因为while循环是空的,它的值永远不会改变,并将while(true)替换为优化。

This... 这个...

while(!buttonPressed){
  // this only works when I have system.out.println("something") written in
}

is just asking for trouble, apart from the fact that you can't guarantee what thread main is actually called in, which could result in you blocking the Event Dispatching Thread, it's just the wrong approach. 只是要求麻烦,除了你不能保证实际调用了什么线程main ,这可能导致你阻止事件调度线程,这只是错误的方法。

Instead of using a JFrame , you want to use a modal JDialog of some kind, which will block the code's execution at the point the dialog is made visible until it is disposed/closed and which does it in safe manner so you can use it within the context of the EDT. 你不想使用JFrame ,而是想要使用某种类型的模态JDialog ,这将阻止代码在对话框可见之前的执行,直到它被处理/关闭,并以安全的方式执行,这样你就可以在内部使用它。 EDT的背景。

Take a look at Initial Threads , Concurrency in Swing and How to Make Dialogs for more details. 有关更多详细信息,请查看初始线程Swing中的并发以及如何创建对话框

As a general piece of advice, avoid extending directly from top level containers like JFrame and JDialog and instead opt of using something like JPanel , it frees you up and increases the reusability of your components 作为一般建议,避免直接从顶级容器(如JFrameJDialog扩展,而是选择使用像JPanel这样的东西,它可以释放你并提高组件的可重用性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM