简体   繁体   English

按下Jbutton后JFrame冻结

[英]JFrame Freezing After Jbutton Pressed

I have been having a problem with my JFrame . 我的JFrame出了问题。 I have added five JButtons for a user interface for an rpg program that I'm working on. 我为我正在研究的RPG程序添加了五个JButtons作为用户界面。 When the "Status" button is pressed, the JFrame freezes, and nothing, not even EXIT_ON_CLOSE works. 按下"Status"按钮时, JFrame冻结,没有任何内容,甚至EXIT_ON_CLOSE也无效。 I want to know how to get the status button to work, and how to avoid this problem with any of the other buttons. 我想知道如何让状态按钮工作,以及如何避免任何其他按钮的这个问题。

Here's the ButtonListener class: 这是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();
            }
        }

    });
}
}

You've got a long-running bit of code here: 你在这里有一长串代码:

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

and since this is running in the Swing event thread, it is tying up the event thread, freezing your application. 因为它在Swing事件线程中运行,所以它会占用事件线程,冻结你的应用程序。 The solution is to avoid doing this, avoid tying up the event thread. 解决方案是避免这样做,避免捆绑事件线程。 Possible solutions depend on your needs including use of a Swing Timer for a game loop, use of a background Thread for long-running processes, or re-constructing your code so that this while loop isn't needed. 可能的解决方案取决于您的需求,包括为游戏循环使用Swing Timer,为长时间运行的进程使用后台线程,或者重新构建代码以便不需要此while循环。

A quick review of your code suggests that perhaps you would want to go the Swing Timer route. 快速查看代码表明您可能想要使用Swing Timer路由。 If you Google Java Swing Timer tutorial you'll get decent info on using this. 如果您使用Google Java Swing Timer tutorial您将获得使用它的正确信息。


As an aside, you are over-using the static modifier and should fix this. 顺便说一下,你过度使用静态修饰符,应该解决这个问题。 You should use this only sparingly and only for specific needs. 您应该谨慎使用它,仅用于特定需求。


Aside number 2: look into the MVC or Model-View-Control design pattern as a way to separate your game logic out of your GUI. 除了第2步:将MVC或模型 - 视图 - 控制设计模式看作是将游戏逻辑从GUI中分离出来的一种方式。 You've got them mixed together in a way that will make extending, improving and debugging your program difficult. 你已经将它们混合在一起,这将使扩展,改进和调试程序变得困难。

Why are you using while(true) an infinite loop whereas you have called break statement in a condition. 你为什么使用while(true)一个无限循环,而你在条件中调用了break语句。 what happened if condition is not matched? 如果条件不匹配会发生什么? Please look it again as shown below. 请再看一遍,如下图所示。

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

When status button is clicked then if(e.getSource() == attack) will never be matched and your program will go in infinite loop. 单击status按钮时, if(e.getSource() == attack)永远不会匹配,您的程序将进入无限循环。

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

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