我无法点击JButton并不断更新Conway的生命游戏。所以我所拥有的是首先给出生命游戏中的规则并模拟和计算计数器的位置。然后通过将背景颜色设置为JButton来更新帧,然后延迟并重复。但问题是,当我按下开始按钮时,由于我试图使用while
循环,它会卡住。
有一个名为AI_Processor的独立包,只是模拟和计算都正确完成,只是更新遇到了一些问题。
代码部分:
public void updateFrame() {
AI.AI_Movement_Update();
addColour();
}
public void addColour() {
for (int i = 0; i < fieldHeight; i++) {
for (int j = 0; j < fieldWidth; j++) {
if (AI.getPosB(j, i) == true) {
testMolecules[i][j].setBackground(Color.green);
} else {
testMolecules[i][j].setBackground(Color.black);
}
}
}
}
Timer tm = new Timer(1000,this);
if (ae.getSource() == start) {
while(true) {
updateFrame();
tm.start();
}
}
答案 0 :(得分:4)
你说:
但问题是当我按下开始按钮时,由于我试图在循环时使用它而导致它被卡住了。
然后摆脱while (true)
循环,因为所有这些都会占用Swing事件线程,使得GUI无用。你有一个Swing Timer,你可以在计时器的ActionListener中调用模型的更新方法,以便在计时器的每次滴答时调用它,然后你就不需要while循环了。其他选项包括保持while (true)
循环,但在后台线程中调用它,但如果这样做,请注意仅在Swing事件线程上更新GUI。
...抱歉格式化......
我已为您格式化了代码,但为了将来参考,您需要阅读本网站的帮助部分,了解如何格式化问题和包含代码。还要看看here。
其他随意的想法:
Timer tm = new Timer(1000,this);
,我尽量避免让我的GUI类实现监听器接口,因为它会强制类做太多,违反单一责任原则。最好使用单独的侦听器类,分配侦听器的Control类或匿名内部类。有关匿名内部类的更多信息,请再次删除while (true)
位,然后尝试类似:
// note that TIMER_DELAY is a constant, and needs to be smaller than 1000, perhaps 20?
Timer tm = new Timer(TIMER_DELAY, new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
updateFrame();
}
});
// the start call below can only be called inside of a method or a constructor
tm.start();
答案 1 :(得分:3)
编辑:
对不起,以前的解决方案很糟糕:-(
编辑:
你可以使用匿名内部类来实现这个
见http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
见http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html
如果使用Timer,则应传递ActionListener的实例 定时器创建一个新的线程,所以虽然不是必要的......
未经测试:
public void updateFrame(){
AI.AI_Movement_Update();
addColour();
}
public void addColour() {
for (int i = 0; i < fieldHeight; i++) {
for (int j = 0; j < fieldWidth; j++) {
if (AI.getPosB(j, i) == true) {
testMolecules[i][j].setBackground(Color.green);
} else {
testMolecules[i][j].setBackground(Color.black);
}
}
}
}
if(ae.getSource() == start)
new Timer(1000,new ActionListener(){
updateFrame();
}).start();