我的 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/