簡體   English   中英

按下Jbutton后JFrame凍結

[英]JFrame Freezing After Jbutton Pressed

我的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();
            }
        }

    });
}
}

你在這里有一長串代碼:

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

因為它在Swing事件線程中運行,所以它會占用事件線程,凍結你的應用程序。 解決方案是避免這樣做,避免捆綁事件線程。 可能的解決方案取決於您的需求,包括為游戲循環使用Swing Timer,為長時間運行的進程使用后台線程,或者重新構建代碼以便不需要此while循環。

快速查看代碼表明您可能想要使用Swing Timer路由。 如果您使用Google Java Swing Timer tutorial您將獲得使用它的正確信息。


順便說一下,你過度使用靜態修飾符,應該解決這個問題。 您應該謹慎使用它,僅用於特定需求。


除了第2步:將MVC或模型 - 視圖 - 控制設計模式看作是將游戲邏輯從GUI中分離出來的一種方式。 你已經將它們混合在一起,這將使擴展,改進和調試程序變得困難。

你為什么使用while(true)一個無限循環,而你在條件中調用了break語句。 如果條件不匹配會發生什么? 請再看一遍,如下圖所示。

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

單擊status按鈕時, if(e.getSource() == attack)永遠不會匹配,您的程序將進入無限循環。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM