I've managed to construct a working code for John Conway's Game of Life.
Now I wish to GUI-ize it.
My only problem is printing a matrix. I want a huge text field to print "_" for no life and "X" for life in each cell (much like I did in cmd version).

Tried with setText, but to no avail.

Recommended Answers

All 17 Replies

"but to no avail", while very poetic, tells us nothing. What was wrong with it? Did you set a mono-spaced font eg Courier?

I'd be satisfied with ANY font/solution.

I'll try to explain my situation in more detail:
You know my code for the game of life? Now, when I run that code I get separate prints for each iteration of the matrix (one below the other). What I want is a GUI text area which will print out the whole array in that same field, so basically an output refresher.

Step by step:
1. Generate initial matrix (as per my code)
2. Print matrix
3. Delete output
4. Generate new matrix (based on initial matrix)
5. Print new matrix
6. Return to step 3 (and do so XX times)

I've tried using jTable, but I simply don't know how to transfer the data from the matrix into the jTable (because, to my understanding, the jTable itself can't actually contain data, just show it).

I'm just looking for a push in the right direction: how to print a 2D array (which is in a loop) in a text area.

PS
I really hope I'm making sense.

You may need to use Thread class in order to simulate an animation. Because of your loop, you won't see anything much in GUI. Or a very simple way is to use actionPerformed() to do the job for you (example).

I see.
I've found out about the javax.swing.JTextArea thingy and I've managed to print the array using JTextArea.append(someString); .

Now I've got to figure out how to format the output and use the timers from Thread.

Wanna see the executible file once I'm done?

Allright. I've now managed to properly generate a new matrix; apply the game-of-life rules; output new matrix.

From Taywin's link I've learnt about timers. And here is where I fail.
I want this:

    private void izračunajNovuMatricuActionPerformed(java.awt.event.ActionEvent evt) {
        M.brojač2++;
        genNum.setText(String.valueOf(M.brojač2));
        izlaz.setText("");
        M.matrica2 = M.izračunajMatricu(M.matrica1);
        M.matrica1 = M.kopirajMatricu(M.matrica2);
        M.čišćenjeMatrice(M.matrica2);
        for (int i = 1; i < M.matrica1.length - 1; i++) {
            for (int j = 1; j < M.matrica1.length - 1; j++) {
                if (M.matrica1[i][j] == false) {
                    izlaz.append(" _ ");
                } else if (M.matrica1[i][j] == true) {
                    izlaz.append(" 0 ");
                }
            }
            izlaz.append("\n");
        }      
    }    

To repeat every half a second.
So far, I've cooked up this bit:

    private void autoGenActionPerformed(java.awt.event.ActionEvent evt) {
        Timer vrijeme;
        vrijeme = new Timer(100, whatGoesHere?);
        vrijeme.setInitialDelay(500);
        vrijeme.start();
        for (;;){

            izračunajNovuMatricuActionPerformed(evt);
            vrijeme.restart();
        }    
    }

Please note that autoGen is a toggle-button. The idea is to press the toggle button and watch the game play itself until the toggle button is pressed again.

You should never ever go into an infinite loop in the event dispatch thread. That would cause your whole application to freeze.

Look at this if you aren't sure how to use javax.swing.Timer:
http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html

I think you want new Timer(500, listener). I put 500 instead of 100 because you said you want it every half-second, not every tenth of a second. The listener is just whatever object you are using to handle the event that happens when your timer goes off.

commented: Good advice +8

Ok. :)

I've completed the program, it works as intended.
I used a timer to animate every new output, used append to properly display the 2D array in the text area.
Is it ok to post completed programs here?
If not, PM me if you want to see it in action (source included).

Thanks to all! :)

I think it is OK to post your solution, but it is up to you anyway.

I took your idea and implemented a GoL class and its GUI display. I could accomplish it without using Timer class. Also, my loop could become infinite if the board keeps changing within 16 steps. The GUI class looks like...

import javax.swing.JFrame;
import javax.swing.JTextArea;
import java.awt.Container;
import java.awt.Font;

class GoLGUIDisplay extends GoL {

  public GoLGUIDisplay(int r, int c) { super(r, c); }

  /*****
   * Return the current matrix for display.
   */
  public String getDisplayString() {
    int rows = getRowSize();
    int cols = getColumnSize();
    String out = "";
    for (int r=0; r<rows; r++) {
      if (r>0) { out += "\n"; }
      for (int c=0; c<cols; c++) {
        out += (getValue(r,c)>0 ? "X" : "_");
      }
    }
    return out;
  }

  /**********
   *  MAIN  *
   **********/
  public static void main(String[] args) {
    int fwidth = 800;
    int fheight = 480;
    int millisec = 80;
    GoLGUIDisplay gol = new GoLGUI(12, 30);  // create matrix with random alive cells
    JFrame jf = new JFrame("Display Game Of Life");
    Container c = jf.getContentPane();
    JTextArea tArea = new JTextArea(10, 100);

    tArea.setText(gol.getDisplayString());
    tArea.setEditable(false);
    tArea.setVisible(true);
    tArea.setFont(new Font(Font.MONOSPACED, Font.BOLD, 12));
    tArea.setBounds(4, 4, fwidth-10, fheight-10);  // arbitrary size
    jf.setLayout(null);  // reset layout manager for absolute positioning
    jf.setResizable(true);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    c.add(tArea);
    jf.setSize(fwidth, fheight);
    jf.setVisible(true);

    System.out.println("... Started Matrix ...");
    System.out.println(tArea.getText());

    // hold on to see the started matrix
    try { Thread.sleep(1000); }
    catch (Exception e) { e.printStackTrace(); }

    while (!gol.isRepeating()) {
      try {
        Thread.sleep(millisec);  // simulate animation
        tArea.setText(gol.getDisplayString());
        gol.computeMatrix();
      }
      catch (Exception e) {
        e.printStackTrace();
        System.exit(1);
      }
    }
    System.out.println("... Result Matrix ...");
    System.out.println(tArea.getText());

    // hold on to see the result matrix
    try { Thread.sleep(1000); }
    catch (Exception e) { e.printStackTrace(); }
    finally { System.exit(0); }
  }
}

Some of the stuff you used is completely new to me. :O
Can I upload .rar directly here or should I use a third-party hosting service and then link it?

Normally, upload file here is OK if it is not too big. Posting on a 3rd party site is OK as well (and Google spider may index your code too).

Pobunjenik - be careful - the approach used in Taywin's code is not one you should follow. "Loops with sleeps" fit very badly with Java Swing, and can behave quite differently on different machines. You will run ito all kinds of problems with that approach as you GUI gets more complex.
Using a Timer was the right way to do this - don't worry.

Ok James, thanks for the headsup! I did in fact use a timer, but not the javax.swing.timer, I used java.util.timer (as I didn't need the more advanced functions, I think).

I did, however, run into one minor problem. I thought that the toggle button would run some code when toggled on, and cease running same code when toggled off. Instead, it seemed to double the speed of the timer (which was in the toggleButtonActionPerformed bit).
So, I took the lazy man's approach: simple button and an exit button right beloew. :D

LINK: http://rapidshare.com/files/3236349148/igraZivota.rar
This contains the .jar and the source code.

NOTE: The program's buttons are all on my native language, and here are the translataions:
Faktor života - Factor of Life
Generiši prvu matricu - Generate initial matrix
Izračunaj novu matricu - Calculate new matrix
Zaustavi i izađi - Stop and exit
Pravila - Rules

In the future, I'll add English and German (somehow).

PS
Daniweb won't let me upload .jar or .rar, so I used RapidShare.

The two Timers do different things.
Javax.swing.Timer executes code on the Swing Event Dispatch Thread, so that code can call any of the Swing methods safely, but equally it will block the swing thread until finished.
java.util.Timer knows nothing of Swing. It's not safe to call (most) swing methods from a jav.util.Timer timer task, but equally a long running task will not block the swing thread. java.util.Timer is also upward compatible with more advanced thread management such as thread pools etc.
You should chose one or the other based on how they need to interact with swing.

I don't have time now to look at your code, but yur symptom is consistent with not stopping the existing timer before starting the new one - 2 timers running = task scheduled twice as often.

I understand that looking at unknown code can be... mind numbing.
I've looked at the methods in the timer class (timer.someAwesomeMethods, if I'm right), and the only thing related to a stopper is the timer.cancel(); one, but that one destroyers the timer.
Now, if I understand this correctly, javax.swing.timer has the timer.start and timer.stop functionalities which could do what I'm looking for.

Another confusion was the toggle button: I thought the code in the button would only be executed while the button is pressed down (toggled on), and stop executing once the button toggles off.

Should I not have used the toggleButtonActionPerformed event?
Should I have used toggleButtonMousePressed and toggleButtonMouseReleased?

Thanks James. That's good to know. I don't do animation on GUI that much. Just want to see if it can be done without a Timer as a quick & dirty implementation. :P

Yes, for a java,util.Timer there's just cancel (AFAIK), after which you just create new Timer when you want to start again. As I said before, it's not the methods that determine your choice of Timer, it's the thread that your code needs to run on.
You get an ActionEvent each time a toggle button is clicked. In your event listener just call your button's isSelected() method to see whether the event was it being selected or de-selected.

Can you send the resource and code?
When i clicked, it does not

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.