按下Jbutton后JFrame冻结

时间:2014-04-13 02:00:20

标签: java swing jframe jbutton freeze

我的JFrame出了问题。我为我正在处理的RPG程序的用户界面添加了五个JButtons。按下"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();
            }
        }

    });
}
}

2 个答案:

答案 0 :(得分:7)

这里有一长串代码:

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

因为它在Swing事件线程中运行,所以它会占用事件线程,冻结你的应用程序。解决方案是避免这样做,避免捆绑事件线程。可能的解决方案取决于您的需求,包括为游戏循环使用Swing Timer,为长时间运行的进程使用后台线程,或重新构建代码,以便不需要此while循环。

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


顺便说一句,你过度使用静态修饰符并应该解决这个问题。您应该谨慎使用它,仅用于特定需求。


除了第2步:调查M-V-C或模型 - 视图 - 控制设计模式,作为将游戏逻辑从GUI中分离出来的一种方式。你已经将它们混合在一起,这将使你的程序扩展,改进和调试变得困难。

答案 1 :(得分:2)

为什么使用while(true)无限循环,而在条件中调用break语句。如果条件不匹配会发生什么?请再看一遍,如下所示。

while(battle1){
    if(e.getSource() == attack){
        ...
        break;
    }
}

点击status按钮后,if(e.getSource() == attack)永远不会匹配,您的程序将无限循环。