等待按钮按下JButton

3

我正在寻找一种方法,使我的程序在等待按下按钮后才继续执行函数。在我的主函数中,我调用一个函数来显示基本的GUI,使用JPanel、按钮和标签。当然,它会显示GUI并结束该函数,不允许我更改GUI。

    public static Player player = new Player();
    public static Gui gui = new Gui();
    public static boolean inMain = true;
    public static boolean inBattle = false;

    public static void main(String[] args){
    showMainGui();  
    }

我认为我需要的是类似下面这样的东西:

我认为我需要的是类似下面这样的东西:

public static void main(String[] args){
    showMainGui();
    while(inBattle == false){
        // wait until inBattle changes
    }
}

那个while循环会一直循环等待,直到在showMainGui创建的一个按钮将inBattle更改为true。我应该如何准确地做到这一点?这让我感到相当困惑。我的目标是单击JButton并更改按钮以显示不同的按钮。

我为在showMainGui()上创建的按钮编写了一个操作侦听器;

public class Hunt implements ActionListener{

    @Override
public void actionPerformed(ActionEvent e) {

    MainClass.inBattle = true;
}
}

这里是我的showMainGui()方法

public static void showMainGui(){
    gui.panel.add(gui.healthLabel);
    gui.panel.add(gui.pbsLabel);
    gui.panel.add(gui.staminaLabel);
    gui.panel.add(gui.levelLabel);

    //Adding initial buttons
    gui.panel.add(gui.exploreButton);
    gui.panel.add(gui.huntButton);
    gui.panel.add(gui.newsLabel);
    gui.panel.add(gui.effectLabel);
    updateGui();

}

你能提供更多的代码吗?你在哪里改变了inBattel和how + showMainGUI方法? - Tala
抱歉,showMainGUI没有给我们任何信息。也许可以更新updateGUI... - Tala
updateGui的作用只是将标签文本设置为变量的值。 - Darryl Chapman
那么调用setVisible方法的是什么?new Gui()吗? - Tala
所以对于你来说有很多东西要学习:)。我建议像这样的东西http://zetcode.com/tutorials/javaswingtutorial/。 - Tala
显示剩余3条评论
5个回答

8

您可以通过使线程休眠来等待。

while(inBattle == false){
    try {
       Thread.sleep(200);
    } catch(InterruptedException e) {
    }
}
// perform operations when inBattle is true

同时不要忘记将 inBattle 变量声明为 volatile


你的GUI正在另一个线程上执行,主线程应该等待,否则它将完成执行并终止。这个inbattle变量是一个共享变量,通过它你正在进行同步。 - Tala
谢谢,我现在明白了,但是如何使变量成为volatile? - Darryl Chapman
只需在声明中添加volatile关键字,即public static volatile boolean inBattle = false; - Tala
我已经做了那个,但似乎没有变化。如果我从主方法中添加我的按钮,而不是调用一个将项目添加到实例的函数,那会起作用吗? - Darryl Chapman
我只展示了如何使线程休眠,还有很多东西需要学习,我已经向作者建议了一篇教程。 - Tala
显示剩余2条评论

5
我会+1 Peter的答案,但我感觉需要更详细的解释。
完全没有必要使用while循环或额外的线程。只需为您的UI组件添加侦听器即可。以下是一个非常简单的示例:
    JButton button = new JButton("This is a button!");

    //Add action listener to button
    button.addActionListener(new ActionListener() {

    public void actionPerformed(ActionEvent e)
    {
        //Perform function when button is pressed
        System.out.println("You clicked the button");
    }
 }); 

你在保留while循环的情况下添加了动作监听器,为什么?移除while循环并使用监听器。
再次重申Peter,但是RTFM。只需阅读文档,其中提供了清晰的示例。没有使用该循环的好理由。

你的应用程序没有崩溃,它正在按照你告诉它要做的事情进行:

public static void main(String[] args){
    showMainGui();
    while(inBattle == false){
        // wait until inBattle changes
    }
}

你的意思是,当 inBattle 为 false 时,什么也不做,但如果 inBattle 为 true,则仍然什么也不做,然后结束主函数 -- 如果没有要做的事情,那么在点击按钮后你希望它做什么?

我已经在我的showMainGui()函数中创建了一个带有动作监听器的按钮。当我使用这个按钮时,它会导致应用程序崩溃。 - Darryl Chapman

1

1
以上的回答并没有解决我的问题,所以我试着用另一种方法。当我搜索“等待按钮按下jbutton”时,这是第一个答案。
我的解决方案使用了等待-通知的概念,并将ActionListener附加到按钮上。它成功地解决了我的问题。
    public void actionPerformed(ActionEvent e) { 
             buttonClicked = true;
             synchronized (b) {
                 b.notify();
                 
             } 
    } 

(对于缩进表示歉意,如果有人想编辑,请随意)当按钮被点击时,这将发送一个通知。然后我附加了一个名为waitForEnter()的方法:

public static void waitForEnter() throws InterruptedException {
        synchronized(b) {
            try {
                
                b.wait();
            } catch (InterruptedException ex) {
                System.out.println("Interrupted");
            }
        }
        System.out.println("After button clicked");
    //... more code
    }

当我调用这个方法时,它会暂停主线程的执行,直到名为“b”的按钮被点击。这对我非常有效。

0

我在阅读这个答案时一直在寻找解决方案,但我意识到如果你想帮助更新你的GUI,这可能会对你有所帮助。

我假设你正在使用JPanels等组件(我是),但你应该尝试这个:

在我的游戏中:

MainWindow window = new MainWindow();
    WelcomePanel welcome = new WelcomePanel(window);
    window.add(welcome);
    window.setVisible(true);

    while (Data.isWelcomeConfigDone != true) {
        try {
            Thread.sleep(500);
        }
        catch (InterruptedException e) {}

    }
    window.validate();
    window.setVisible(false);
    window.remove(welcome);

    GamePanel game = new GamePanel(window, welcome);

    window.add(game);
    window.setVisible(true);
    game.setVisible(true);

    while (true) {}

我和你有相同的想法,只需循环直到我的条件为假。然而,我感觉那个家伙没有更新,所以你需要添加这个:

window.validate(); // or whatever it is. My window is a JFrame, 
                      but it should work in a JPanel

我知道这已经很晚了,但对于任何出现在这个问题中的人,这应该会有所帮助。

validate()文档:

public void validate() 验证此容器及其所有子组件。 当修改此容器的子组件(添加到容器中或从容器中删除,或更改与布局相关的信息)后,应使用验证方法使容器重新布置其子组件。

如果此容器无效,则此方法将调用validateTree方法并将此容器标记为有效。否则,不执行任何操作。

覆盖: Component类中的validate 参见: add(java.awt.Component), Component.invalidate(), JComponent.revalidate(), validateTree()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接