java - 按下 Jbutton 后 JFrame 卡住

标签 java swing jframe jbutton freeze

我的 JFrame 遇到了问题。我为我正在开发的角色扮演游戏程序的用户界面添加了五个 JButton。当按下“Status”按钮时,JFrame卡住,什么都没有,甚至EXIT_ON_CLOSE也不起作用。我想知道如何让状态按钮正常工作,以及如何避免其他按钮出现此问题。

这是 ButtonListener 类:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;


public class ButtonListeners {
public static final int WIDTH=360;
public static final int HEIGHT=360;
final static Monsters sk = new Monsters("Skeleton",120,20,30,5,50);
final static Monsters dm = new Monsters("Dark Mage",130,10,40,10,100);
final static Monsters kn = new Monsters("Knight",160,30,40,2,120);
final static Monsters sm = new Monsters("Slime",200,1,50,5,150);
final static Monsters go = new Monsters("golem",500,50,55,15,400);
final static Monsters dg = new Monsters("dragon",1000,35,100,25,600);
final static Monsters bk = new Monsters("Black Knight",2000,35,90,12,1000);
final static Monsters zm = new Monsters("Zombie",100,30,35,5,50);
public static void UI(){
    final JFrame frame=new JFrame("Guantlet");
    frame.setSize(800,600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    final Player p = new Player();
    frame.setSize(WIDTH,HEIGHT);
    final JButton item = new JButton("Items");
    final JButton status=new JButton("Status");
    final JButton attack=new JButton("Attack");
    final JButton defend = new JButton("Defend");
    final JButton mStat = new JButton("Monster Status");
    frame.setVisible(true);
    frame.add(attack,BorderLayout.EAST);
    frame.add(defend,BorderLayout.WEST);
    frame.add(item, BorderLayout.NORTH);
    frame.add(status, BorderLayout.SOUTH);
    frame.add(mStat, BorderLayout.CENTER);

    final ArrayList<Monsters> monOrder = new ArrayList<Monsters>();
    monOrder.add(0,sk);
    monOrder.add(1,zm);
    monOrder.add(2,kn);
    monOrder.add(3,sm);
    monOrder.add(4,dm);
    monOrder.add(5,go);
    monOrder.add(6,dg);
    monOrder.add(7,bk);
    frame.setVisible(true);
    JOptionPane.showMessageDialog(frame, "Welcome to the arena! Many opponents await.");

    JOptionPane.showMessageDialog(frame,"A Skeleton draws near!");

    class Button1Listener implements ActionListener{


        @Override
        public void actionPerformed(ActionEvent e) {
            boolean battle1 = true;

            while(battle1){

                if(e.getSource() == attack){// &&monOrder.contains(sk) && monOrder.contains(zm) && monOrder.contains(kn) && monOrder.contains(dm) && monOrder.contains(go) && monOrder.contains(dg)&& monOrder.contains(bk)) {
                    if(monOrder.contains(sk)){


                        sk.mHP=sk.mHP-sk.attacked(p);
                        sk.status();
                        sk.isAlive();
                        if(sk.isAlive()){
                            p.hp=p.hp-sk.attacking(p);
                            System.out.println("The Skeleton has "+sk.mHP+" health left");
                            System.out.println("You have "+"You have "+p.hp+ " health left");
                            p.status();
                        }else if(!sk.isAlive()){
                            monOrder.remove(0);
                            p.exp=p.exp+sk.exp;
                            p.levelUp();
                            JOptionPane.showMessageDialog(frame,"A Zombie emerges!");

                        }
                        //}



                        System.out.println(zm.mHP);

                    }
                    if(monOrder.contains(zm) && !monOrder.contains(sk)){
                        zm.mHP=zm.mHP-zm.attacked(p);

                        zm.status();

                        zm.isAlive();
                        if(zm.isAlive()){
                            p.hp=p.hp-zm.attacking(p);
                            System.out.println("The Skeleton has "+zm.mHP+" health left");
                            System.out.println("You have "+"You have "+p.hp+ " health left");
                            p.status();
                        }else if(!zm.isAlive()){
                            monOrder.remove(0);
                            p.exp=p.exp+zm.exp;
                            p.levelUp();
                            JOptionPane.showMessageDialog(frame,"A Dark Mage appears before you!");

                        }
                    }
                    break;
                }
            }


        }

    }

    ActionListener b1L=new Button1Listener();

    attack.addActionListener(b1L);

    status.addActionListener(b1L);

    status.addActionListener(new ActionListener() { 
        @Override
        public void actionPerformed(ActionEvent e) {
            if(e.getSource() == status ){

                JOptionPane.showMessageDialog(frame, "Maximum Health = " + p.maxHP+" \n Strength = " + p.str + "\n Speed = "+p.spd+"\n Experience to next level- "+(p.reqExp-p.exp));
                Thread t = new Thread(new Runnable() {
                    public void run() {

                        // execute query here

                        SwingUtilities.invokeLater(new Runnable() {
                            public void run() {

                                // update the ui here
                                final JFrame frame=new JFrame("Guantlet");
                                frame.setSize(800,600);
                                frame.add(attack,BorderLayout.EAST);
                                frame.add(defend,BorderLayout.WEST);
                                frame.add(item, BorderLayout.NORTH);
                                frame.add(status, BorderLayout.SOUTH);
                                frame.add(mStat, BorderLayout.CENTER);

                            }
                        });
                    }
                });
                t.start();
            }
        }

    });
}
}

最佳答案

这里有一段长时间运行的代码:

while(battle1){
  //....
}

由于它在 Swing 事件线程中运行,因此它会占用事件线程,从而卡住您的应用程序。解决方案是避免这样做,避免占用事件线程。可能的解决方案取决于您的需求,包括为游戏循环使用 Swing 计时器、为长时间运行的进程使用后台线程,或者重新构建代码以便不需要此 while 循环。

快速查看您的代码表明您可能想要采用 Swing Timer 路线。如果您 Google Java Swing Timer 教程,您将获得有关使用它的有用信息。

<小时/>

顺便说一句,您过度使用了 static 修饰符,应该解决这个问题。您应该谨慎使用它,并且仅在满足特定需求时使用它。

<小时/>

旁白第二点:研究 M-V-C 或模型- View -控制设计模式,将其作为将游戏逻辑与 GUI 分离的方法。您将它们混合在一起,这将使扩展、改进和调试程序变得困难。

关于java - 按下 Jbutton 后 JFrame 卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23038286/

相关文章:

不使用 IDE 时的 Java 和编译

java - 如何帮助 JAXB 解码器在两个相似的类之间正确选择

java - 在面板中创建另一列的按钮

java - 如何使用 setVisible(false) 从 JFrame 创建图像?

java - Spring MVC 3.0 注解 - 对话形式 - 初学者问题

java - 以静态方法访问spring bean

鼠标移动时忽略 Java 鼠标事件?

java - 让jbutton打开和关闭

java - 如何将文本区域(JTextArea)放入窗口(JFrame)中?

Java Graphics 尝试绘制矩形