Java 在循环冻结程序时继续计算,并在计算之间暂停
您好,我有一段代码,您可以单击几个多维数据集将它们设置为死的或活的,并且根据一组规则,java将在下一步后计算哪些单元格将是活的/死的Java 在循环冻结程序时继续计算,并在计算之间暂停,java,Java,您好,我有一段代码,您可以单击几个多维数据集将它们设置为死的或活的,并且根据一组规则,java将在下一步后计算哪些单元格将是活的/死的 import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; class GameOfLife implements ActionListener{ Scanner scanner;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
class GameOfLife implements ActionListener{
Scanner scanner; //to read the text file
File file;
boolean play = false;
String filename = "birth.txt"; //the file that has to be read
Cell[][] cells=new Cell[10][10]; //array containing all the cells
JButton nextButton;
JButton playButton;
JPanel buttonPanel;
JPanel cellPanel;
GridLayout gridLayout=new GridLayout(10,10);
JFrame frame=new JFrame();
void buildit(){
readInput();
frame.setSize(600,700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel=new JPanel();
buttonPanel.setPreferredSize(new Dimension(600,100));
frame.add(buttonPanel, BorderLayout.PAGE_START);
nextButton=new JButton("Next generation");
playButton=new JButton("Play");
nextButton.setPreferredSize(new Dimension(150,50));
playButton.setPreferredSize(new Dimension(150,50));
nextButton.addActionListener(this);
playButton.addActionListener(this);
frame.add(nextButton, BorderLayout.LINE_START);
frame.add(playButton, BorderLayout.LINE_END);
cellPanel=new JPanel();
cellPanel.setLayout(gridLayout); //gives the panel a gridlayout
cellPanel.setPreferredSize(new Dimension(600,600));
frame.add(cellPanel, BorderLayout.PAGE_START);
for(int i=0; i<100; i++){
cells[i%10][i/10]=new Cell(); //i/10 will be rounded down, so it equals the rownumber
cellPanel.add(cells[i%10][i/10]);
cells[i%10][i/10].addMouseListener(cells[i%10][i/10]); //add a mouselistener to the cell
cells[i%10][i/10].setOpaque(true); //makes the backgroundcolor visible
cells[i%10][i/10].setBackground(Color.BLACK);
cells[i%10][i/10].setBorder(BorderFactory.createLineBorder(Color.WHITE));
}
frame.setVisible(true);
for(int i=0; i<100; i++){
for(int j=0; j<9; j++){
if((i%10-1+j%3>=0) && (i%10-1+j%3<10) && (i/10-1+j/3>=0) && (i/10-1+j/3<10) && !(j==4)){ //exclude cells that are outside the frame (non existant) and the cell itself
cells[i%10][i/10].setNeighbours(cells[i%10-1+j%3][i/10-1+j/3]); //this adds all the neighbours to the arraylist
}
}
}
}
public void actionPerformed(ActionEvent e){
if(e.getSource()==nextButton){
for(int i=0; i<100; i++){
cells[i%10][i/10].calculateNextState();
}
for(int i=0; i<100; i++){
cells[i%10][i/10].updateToNextState();
}
}
else{if (e.getSource()==playButton) {
play = true;
for (int p=0; p<3;p++) {
for(int i=0; i<100; i++){
cells[i%10][i/10].calculateNextState();
}
for(int i=0; i<100; i++){
cells[i%10][i/10].updateToNextState();
}
}
}
}
}
void readInput(){
try{
file = new File( filename);
scanner = new Scanner( file );
String nextGen=""; //this string will contain the output
int row=scanner.nextInt(); //read the row number
int col=scanner.nextInt(); //and the column number
Cell[][] cellen=new Cell[row][col]; //array containing all the cells
for(int i=0; i<row*col; i++){
cellen[i%row][i/col]=new Cell();
if(scanner.next().equals(".")){
cellen[i%row][i/col].setState(CellState.alive); //set the state
}
else{
cellen[i%row][i/col].setState(CellState.dead);
}
}
for(int i=0; i<row*col; i++){
for(int j=0; j<9; j++){
if((i%row-1+j%3>=0) && (i%row-1+j%3<row) && (i/col-1+j/3>=0) && (i/col-1+j/3<col) && !(j==4)){
cellen[i%row][i/col].setNeighbours(cellen[i%row-1+j%3][i/col-1+j/3]); //set the neighbours
}
}
}
for(int i=0; i<row*col; i++){
cellen[i%row][i/col].calculateNextState(); //calculate the next state for all the cells
}
for(int i=0; i<row*col; i++){
cellen[i%row][i/col].updateToNextState(); //update all the cells to the next state
}
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
if(cellen[i%row][i/col].getCurrentState()==CellState.alive){ //the cell is alive if getCurrentState is true
nextGen+="*";
}
else{
nextGen+=".";
}
}
nextGen+=System.getProperty("line.separator"); //add an enter after each row
}
System.out.println(nextGen); //print the next generation to the console
}
catch(FileNotFoundException e) {
System.out.println( "Could not find or open file <"+filename+">\n"+e );
}
}
public static void main(String[] args) {
new GameOfLife().buildit();
}
}
import javax.swing.*;
导入java.awt.*;
导入java.awt.event.*;
导入java.util.*;
导入java.io.*;
GameOfLife类实现ActionListener{
Scanner Scanner;//读取文本文件
文件;
布尔播放=假;
String filename=“birth.txt”;//必须读取的文件
单元格[][]单元格=新单元格[10][10];//包含所有单元格的数组
JButton nextButton;
JButton播放按钮;
JPanel按钮面板;
杰帕内尔小组;
GridLayout GridLayout=新的GridLayout(10,10);
JFrame=新JFrame();
void buildit(){
readInput();
框架尺寸(600700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel=新的JPanel();
按钮面板设置首选尺寸(新尺寸(600100));
frame.add(按钮面板,边框布局,页面开始);
nextButton=新的JButton(“下一代”);
playButton=新的JButton(“Play”);
设置首选尺寸(新尺寸(150,50));
playButton.setPreferredSize(新尺寸(150,50));
addActionListener(这个);
playButton.addActionListener(此);
frame.add(下一个按钮,BorderLayout.LINE_START);
帧。添加(播放按钮,边框布局。线条结束);
cellPanel=新的JPanel();
setLayout(gridLayout);//为面板提供gridLayout
cellPanel.setPreferredSize(新尺寸(600600));
frame.add(单元面板、边框布局、页面开始);
对于(int i=0;i来说,这里的问题是您的代码在中运行,这意味着您所做的一切都必须在返回到响应按钮单击和图形更改之前完成
我建议你研究一下:
- 作为启动复杂或耗时任务的一种方式
- 作为一种定期重新计算和步进模拟的方法
正如其他人所评论的,您应该真正研究线程和同步
线程允许您同时执行多项任务,而无需使用循环,也不会阻塞代码。这对于需要同时执行多项任务的应用程序编程来说是一个重要方面。您可以了解线程
同步保持一致性,并确保操作相同数据(变量、对象等)的多个线程能够正确计算。您可以了解同步
线程需要一些参数,但最重要的参数是Runnable
。您的Runnable
将保存希望线程运行的代码。您可以将Runnable传递给对象。有多种方法,但创建包含Runnable的线程的两种最简单的方法是:
Runnable myRunnable = new Runnable() {
public void run() {
//your code here
}
}
Thread thread = new Thread(myRunnable);
还有一种更常见的方法:
Thread thread = new Thread(new Runnable() {
public void run() {
}
});
现在,希望您对线程有了更好的理解(我强烈建议您阅读Oracle的试用版以了解完整的细节),我们就可以了解您想要做的事情了
您需要计算代码,在每次计算之间,您需要1秒的延迟。这就是Thread.sleep()
方法的作用
Thread.sleep()
允许您将线程暂停一定时间。在每次计算之间查看您希望如何执行,您希望将其放在实际代码的末尾(因为它将在循环中)
现在,正如我前面提到的,如果你想在包含UI的类之外操作你的UI,你必须使用SwingUtilities
invokeLater()
,以触发UIThread中的代码,但在类之外。这个方法也将Runnable作为参数
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//code to manipulate frame/panel/applet
}
});
顺便说一句,Runnable被认为是一个功能接口。功能接口是只包含一个方法的接口。这是一些(从我看到的)在interface试用版中没有列出的信息,这就是为什么我现在让你知道这个术语。你可以查看接口
简单的方法是将Thread.sleep(1000)放入循环中,以使进度可见,并仅使用SwingUtilities.invokeLater()更新UI。这不是一个很好的解决方案,但应该可以使用。您需要在单独的线程上运行计算。您应该只在UI线程上执行UI交互,并执行其他可能需要一段时间的操作(网络连接、计算)在一个后台线程上,当UI有内容要显示时更新它。创建一个有while循环的线程,创建一个在按下按钮时触发的布尔值,然后在循环中,创建一个条件“if boolean is true”,然后thread.sleep 1000毫秒,然后停止线程。如果没有人为此发布代码,我将编写一些when我到家了。现在在我的手机上。编辑:如果你想在App/Panel/Frame类之外与UIThread交互,那么使用SwingUtilities.invokeLater(new Runnable(){public void run(){操纵Frame/Panel的代码});我建议您从阅读线程开始—如何创建线程、如何启动线程、如何使线程睡眠,以及如果在线程睡眠时中断线程会发生什么。您需要一个线程来进行计算,当用户单击“停止”时,您将中断该线程button.Vince Emigh EDIT:编写的代码将非常重要。我已经发布了一些信息作为答案。请查看,有一些非常有用的链接,并解释如何处理循环情况。因此,如果我理解正确,我应该将其他{if(e.getSource()==playButton){play=true;用于(int p=0;pNo,您的按钮应该检查线程是否处于活动状态。如果不是,则play=true;
和boolean running;
Thread thread = new Thread(new Runnable() {
public void run() {
while(running) {
//calculation code
Thread.sleep(1000); //counted in miliseconds
}
}
});
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//code to manipulate frame/panel/applet
}
});
boolean play = false;
public void actionPerformed(ActionEvent e) {
if
play = !play;
if(play) {
if(!thread.isAlive())
thread.start();
} else {
if(thread.isAlive()) {
thread.interrupt();
try { thread.join(); }catch(InterruptedException e) { }
}
}
}