Starting and Stopping a loop with JButtons
Ok, I'm programming my own Conway's Game Of Life Simulator. Right now I just want to get the basic program down before adding a bunch of horns a whistles. I'm using the acm library. I have one class extending JPanel that puts up the buttons and controls for the other class that extends GCanvas that displays the grid. My goal right now is to be able to press "Start" and have the grid progress in their generations until the "Stop" button is pressed. Following is my code, any ideas?
Code Java:
import javax.swing.*;
import java.awt.*;
@SuppressWarnings ("serial")
public class GameOfLifeApp extends JFrame {
// constructor
public GameOfLifeApp (String title, String fname) {
// calls superclass JFrame to create window
super(title);
this.setSize(800, 600);
// create two panels and add them to the JFrame
LifePanel panel = new LifePanel(fname);
ControlPanel controlPanel = new ControlPanel(panel);
this.add(panel, BorderLayout.CENTER);
this.add(controlPanel, BorderLayout.PAGE_END);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
//main method
public static void main (String [] args) {
new GameOfLifeApp("Game of Life", "src/exploder.txt");
}
}
Code Java:
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
@SuppressWarnings("serial")
public class ControlPanel extends JPanel implements ActionListener {
JPanel control;
JSlider Speed;
JButton Previous, Start, Next, Stop, Quit;
LifePanel Display;
public ControlPanel(LifePanel panel) {
super();
Display = panel;
Speed = new JSlider(JSlider.HORIZONTAL, 1, 10, 1);
control = new JPanel();
Start = new JButton("Start");
Stop = new JButton("Stop");
Quit = new QuitButton();
Speed.setMajorTickSpacing(1);
Speed.setMinorTickSpacing(1);
Speed.setPaintTicks(true);
Speed.setPaintLabels(true);
Speed.addChangeListener(new SliderListener());
Start.addActionListener(this);
Stop.addActionListener(this);
control.add(Start);
control.add(Stop);
control.add(Speed);
control.add(Quit);
this.add(control);
setVisible(true);
}
private class SliderListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Start) {
}
}
}
Code Java:
import acm.graphics.*;
import java.io.*;
@SuppressWarnings("serial")
public class LifePanel extends GCanvas {
public char VALUE[][][] = new char [3][20][30];
public String FILE;
public GRect Cell;
public boolean active = false;
public LifePanel(String f) {
OpenFile(f);
DrawGrid();
}
public void OpenFile(String f) {
String FILE = f;
FileInputStream fis = null;
try {
fis = new FileInputStream(FILE);
} catch (FileNotFoundException e) {
System.out.println("File Not Found");
}
try {
int temp, x = 0, y = 0;
while (x != 20) {
while (y != 30) {
temp = fis.read();
if (temp == 10)
temp = fis.read();
VALUE[1][x][y] = (char) temp;
y++;
}
y = 0;
x++;
}
} catch (IOException e) {
System.out.println("Error reading file");
}
}
public void DrawGrid() {
this.removeAll();
int x = 0, y = 0;
while (x != 20) {
while (y != 30) {
Cell = new GRect(15,15);
if (VALUE[1][x][y] == (char) 48)
Cell.setFillColor(java.awt.Color.BLUE);
else
Cell.setFillColor(java.awt.Color.YELLOW);
Cell.setFilled(true);
add(Cell,x*15+250,y*15+10);
y++;
}
y = 0;x++;
}
}
public void NextGeneration() {
int x=0,y=0,f=-1,g=-1,on=0;
while (x != 20) {
while (y != 30) {
while (f != 2) {
while (g != 2) {
try {
if (VALUE[1][x+f][y+g] == (char) 49)
on++;
g++;
} catch (ArrayIndexOutOfBoundsException e) {
g++;
}
}
f++;g=-1;
}
VALUE[2][x][y] = VALUE[1][x][y];
if (VALUE[1][x][y] == (char) 49)
on--;
if (VALUE[1][x][y] == (char) 49 && ((on<2) || (on>3)))
VALUE[2][x][y] = (char) 48;
if (VALUE[1][x][y] == (char) 48 && on == 3)
VALUE[2][x][y] = (char) 49;
y++;f=-1;on=0;
}
y = 0;x++;
}
x=0;y=0;
while (x != 20) {
while (y != 30) {
VALUE[1][x][y] = VALUE[2][x][y];
y++;
}
x++;y=0;
}
}
}
Only thing I didn't add was my QuitButton code, but that's just a simple System.exit function. I'm guessing my loop issue would be in ControlPanel.java. Please let me know what I should do
Re: Starting and Stopping a loop with JButtons
Code java:
import javax.swing.*;
import java.awt.*;
@SuppressWarnings ("serial")
public class GameOfLifeApp extends JFrame {
// constructor
public GameOfLifeApp (String title, String fname) {
// calls superclass JFrame to create window
super(title);
this.setSize(800, 600);
// create two panels and add them to the JFrame
LifePanel panel = new LifePanel(fname);
ControlPanel controlPanel = new ControlPanel(panel);
this.add(panel, BorderLayout.CENTER);
this.add(controlPanel, BorderLayout.PAGE_END);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
this.setVisible(true);
}
//main method
public static void main (String [] args) {
new GameOfLifeApp("Game of Life", "src/exploder.txt");
}
}
--------------------
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
@SuppressWarnings("serial")
public class ControlPanel extends JPanel implements ActionListener {
JPanel control;
JSlider Speed;
JButton Previous, Start, Next, Stop, Quit;
LifePanel Display;
public ControlPanel(LifePanel panel) {
super();
Display = panel;
Speed = new JSlider(JSlider.HORIZONTAL, 1, 10, 1);
control = new JPanel();
Start = new JButton("Start");
Stop = new JButton("Stop");
Quit = new QuitButton();
Speed.setMajorTickSpacing(1);
Speed.setMinorTickSpacing(1);
Speed.setPaintTicks(true);
Speed.setPaintLabels(true);
Speed.addChangeListener(new SliderListener());
Start.addActionListener(this);
Stop.addActionListener(this);
control.add(Start);
control.add(Stop);
control.add(Speed);
control.add(Quit);
this.add(control);
setVisible(true);
}
private class SliderListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Start) {
}
}
}
--------------------
import acm.graphics.*;
import java.io.*;
@SuppressWarnings("serial")
public class LifePanel extends GCanvas {
public char VALUE[][][] = new char [3][20][30];
public String FILE;
public GRect Cell;
public boolean active = false;
public LifePanel(String f) {
OpenFile(f);
DrawGrid();
}
public void OpenFile(String f) {
String FILE = f;
FileInputStream fis = null;
try {
fis = new FileInputStream(FILE);
} catch (FileNotFoundException e) {
System.out.println("File Not Found");
}
try {
int temp, x = 0, y = 0;
while (x != 20) {
while (y != 30) {
temp = fis.read();
if (temp == 10)
temp = fis.read();
VALUE[1][x][y] = (char) temp;
y++;
}
y = 0;
x++;
}
} catch (IOException e) {
System.out.println("Error reading file");
}
}
public void DrawGrid() {
this.removeAll();
int x = 0, y = 0;
while (x != 20) {
while (y != 30) {
Cell = new GRect(15,15);
if (VALUE[1][x][y] == (char) 48)
Cell.setFillColor(java.awt.Color.BLUE);
else
Cell.setFillColor(java.awt.Color.YELLOW);
Cell.setFilled(true);
add(Cell,x*15+250,y*15+10);
y++;
}
y = 0;x++;
}
}
public void NextGeneration() {
int x=0,y=0,f=-1,g=-1,on=0;
while (x != 20) {
while (y != 30) {
while (f != 2) {
while (g != 2) {
try {
if (VALUE[1][x+f][y+g] == (char) 49)
on++;
g++;
} catch (ArrayIndexOutOfBoundsException e) {
g++;
}
}
f++;g=-1;
}
VALUE[2][x][y] = VALUE[1][x][y];
if (VALUE[1][x][y] == (char) 49)
on--;
if (VALUE[1][x][y] == (char) 49 && ((on<2) || (on>3)))
VALUE[2][x][y] = (char) 48;
if (VALUE[1][x][y] == (char) 48 && on == 3)
VALUE[2][x][y] = (char) 49;
y++;f=-1;on=0;
}
y = 0;x++;
}
x=0;y=0;
while (x != 20) {
while (y != 30) {
VALUE[1][x][y] = VALUE[2][x][y];
y++;
}
x++;y=0;
}
}
}
Re: Starting and Stopping a loop with JButtons
Your whole class is a JPanel. Why are you adding another JPanel to it?
I've done it where I've had a whole class that was a JFrame but I used a JPanel to put everything on, that way I could add scrollbars.
Re: Starting and Stopping a loop with JButtons
Quit = new QuitButton();
This is a bad idea. You've told Quit that it's an object of class QuitButton.
Unless you have a class called QuitButton.
Re: Starting and Stopping a loop with JButtons
Yea, I see the redundancy with the JPanel and I'll probably fix that later;
As I said above, I did not include my QuitButton class because it didn't have anything to do with my question;
I need to know how to start a loop that performs NextGeneration() and DrawGrid() repeatedly until the Stop button is pressed. I want to click "start" have the grid perform the generations and then stop when I press "stop". Once I can do that, I can ad the other features I intend to add
Re: Starting and Stopping a loop with JButtons
Ok so make the action of the start button call a method that does those two actions in a loop. Make the loop continue while a boolean variable called keepDrawing (or whatever you want to name it) is true. Make the stop button set that boolean to false.
This isn't really the best solution, but it probably works for what you need.
Note: This requires your GUI and processing to be done in different threads.
Re: Starting and Stopping a loop with JButtons
Code java:
public void Draw() {
while (keepDrawing == true) {
NextGeneration();
DrawGrid();
}
}
I added this to LifePanel.java
Code java:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Start) {
Display.keepDrawing = true;
Display.Draw();
} else
Display.keepDrawing = false;
}
and I made this the actionPerformed method. Now whenever I click "start" it freezes
Re: Starting and Stopping a loop with JButtons
Hence the reason why DavidFongs suggested you place the work in a different thread. The current implementation throws the event dispatch thread (which does all swing drawing and actions) into your infinite loop.
See
Lesson: Concurrency
SwingWorker
Make sure if you use a custom thread, all updates to swing should be placed onto the event dispatch thread using SwingUtilities.
Re: Starting and Stopping a loop with JButtons
yea, I heard I'd have to look into threads, but I've never really used them before. This is the most complicated program I've made so far (Just started java this semester). I'll look over those tutorials and see if I can figure it out. If anyone can give me a quick tutorial on it though, that would be much appreciated.