我在Java swing中实现了Conway's Game of Life问题。一切都很好。正如您在下面的屏幕截图中看到的,只要单击“勾选”按钮,游戏就会进入下一个生命形式。现在,我计划在“Tick”按钮旁边添加一个“Autoplay”按钮。这种自动播放的目的很简单。当我点击它时,应该继续进行自动操作,就好像我以1秒的间隔按下勾选按钮。
我试过这个。但这似乎阻止了所有其他操作。如何在单独的线程中执行此操作?一个小代码片段会让我走。
class AutoPlayListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnAutoPlay){
while(true){
Thread.sleep(1000); //InterruptedException try catch hidden
btnTick.doClick();
}
}
}
}
答案 0 :(得分:6)
使用javax.swing.Timer
。如果删除ActionListener
和while(true)
来电,则可以使用现有的Thread.sleep()
。
答案 1 :(得分:2)
有两种选择:
repaint()
或invalidate()
,告诉它需要重新绘制。在actionPerformed
方法中,创建一个新线程。并调用其启动方法。
线程的Runnable
应该运行一个while循环(就像你已经完成的那样),然后只需退出。
在类型为Timer的类中创建一个对象。如果使用swing,请使用java.swing.Timer
中的那个(还有java.util.Timer
,这对GUI操作不利)。计时器应该有ActionListener
调用你的方法一次,但Timer的重复率为1000ms。
e.g。
tickButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
doTick();
}
});
停止线程的机制同样重要!一般情况下,不要在线程中使用while(true)
因为它会丢失;发明一个信号量来终止它。
使用JToggleButton
而不是Button
?
同步: 如果你使用线程,你将需要这样的东西,以防止每次按下按钮时创建新线程:
代码
Thread autoplayThread = null;
Object lock;
boolean autoplaying = false;
public void actionPerformed(ActionEvent e){
synchronized(lock){ // prevent any race condition here
if(!autoplaying && autoplayThread==null ){
autoplaying = true;
autoplayThread = new Thread(new Runnable(){
public void run(){
try{
while(autoplaying){ .... }
}finally{
synchronized(lock) {
autoplaying=false;
autoplayThread=null;
}
}
}
});
autoplayThread.start();
}else{ // stop the thread!
autoplaying=false;
}
}
}
答案 2 :(得分:2)
正如@Ranman所说,你正在阻止主UI线程。我相信SwingUtilities.invokeLater通常用于这样的事情。