0

I am doing an cellular automaton exercise in java and I came across a problem.

The logical part of the CA is working fine, if I wanted it to be arranged on the console it would be ready, but I want it to be drawn on the panel, when it is 1 drawing a black square, when it is 0 drawing a white square

Let's go to the problem

What is happening is that the whole logic runs normally, but when drawing java only draws the latest generation of CA, I read that java paintComponent only works when java decides to and not when it is called.

My question is: how the best way to solve this problem and how to do it.

I thought of some things, but as I don't know java so well I decided to ask you

I thought about maybe saving all Arrays into one and then drawing from it (but I don't know how I could do it) I thought maybe there was a method of drawing in each loop, but I didn't find it (I used repaint () but it was no use)

Anyway, I would be grateful if someone gave me a solution, I have this problem for days and I have not found a solution, below is all the code

import java.awt.BorderLayout;

import javax.swing.JFrame;    
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class CA extends JFrame {

    Rules rules = new Rules();

    public CA() {
        super("Cellular Automaton");
        setLayout(new BorderLayout());
        add(new GUI_CA(), BorderLayout.CENTER);
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        setVisible(true);

    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                new CA();
            }   
        }); 
      }
    }
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Arrays;

import javax.swing.BorderFactory;
import javax.swing.JPanel;    

@SuppressWarnings("serial")
public class GUI_CA extends JPanel {

    int cellSize = 10;

    Rules rules = new Rules();

    private BufferedImage img;
    private Graphics2D g2d;

    public GUI_CA() {

        img =  new BufferedImage(cellSize, cellSize, BufferedImage.TYPE_INT_RGB);
        g2d = (Graphics2D) img.createGraphics();

        evolution();    
    }

    public void evolution() {
        rules.cells = new int[987/cellSize];
        rules.cells[rules.cells.length/2] = 1;
        System.out.println(Arrays.toString(rules.cells));
        for (int generationCount = 0; generationCount < 10; generationCount++) {
            rules.generate();
            System.out.println(Arrays.toString(rules.cells));
            repaint();
        }           
    }

    public void drawCA(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        for (int i = 1; i < rules.cells.length -1; i++) {

            if (rules.cells[i] == 1) {
                g2d.setColor(Color.BLACK);
                g2d.fillRect(i * cellSize, rules.generation * 5, cellSize, cellSize);
                System.out.println(Arrays.toString(rules.cells));
            }else {
                g2d.setColor(Color.WHITE);
                g2d.fillRect(i * cellSize, rules.generation * 5, cellSize, cellSize);
            }
        }


    }

    public void drawBackground(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        int width = 987;
        int height = 545;

        g2d.setPaint(Color.WHITE);
        g2d.fillRect(0, 0, width, height);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawBackground(g);
        drawCA(g);
        g.drawImage(img, 0, 0, null);

    }

    public Dimension getPreferredSize() {
        return new Dimension(987, 545);
    }

}
public class Rules {

    int[] cells;
    int[] ruleSet = new int[] {0, 1, 1, 1, 1, 0, 0, 0};
    //int cellSize = 10;
    int generation = 0;


    void generate() {

        int[] nextGeneration = new int[cells.length];

        for (int i = 1; i < cells.length - 1; i++) {

            int left = cells[i - 1];
            int me = cells[i];
            int right = cells [i + 1];

            nextGeneration[i] = rules(left, me, right);
        }
        cells = nextGeneration;
        generation++;

    }

    int rules(int left, int me, int right) {
        String s = "" + left + me + right;
        int index = Integer.parseInt(s, 2);
        //System.out.println(index);
        return ruleSet[index];      
    }
}
Andre Dilay
  • 52
  • 1
  • 9

1 Answers1

0

GUI programming is different than console programming because you have to use the event system instead of just a while loop to repeat a task that generates output. I suggest that you start by adding a button that the user clicks to advance to the next generation of the automaton. When you get that working, you can take it a step further to add a timer that automatically goes to the next generation after a certain amount of time.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Thanks for the suggestion, that's helps a lots. I definitely will do this, thanks. Is there a way to the program do all de logic and then draw all the generations in one piece? – Andre Dilay Oct 08 '19 at 20:22
  • @AndreDilay What do you mean "draw all the generations in one piece"? What do you want the user to see on the screen? – Code-Apprentice Oct 08 '19 at 20:34
  • i want to draw all the generations, the user will see the final pattern – Andre Dilay Oct 09 '19 at 02:45
  • Final pattern in case of CA usually means final generation, not all generations at once. Because what do you do for a final pattern if half the time a cell was white and the other half it was black? Draw it in grey? Or have a fully black/white screen? – M. Prokhorov Oct 09 '19 at 11:07
  • I want to do something like this [rule 30] (https://www.google.com/search?q=rule+30+wolfram&safe=active&sxsrf=ACYBGNRmlQ6IqMTpPhLxJ3AnVTW0c0mWbg:1570623468672&source=lnms&tbm=isch&sa=X&ved=0ahUKEwiD9bOvlI_lAhU5IrkGHZpUAbIQ_AUIEigB&biw=1366&bih=625#imgrc=_) and is that the user will see – Andre Dilay Oct 09 '19 at 12:19
  • @AndreDilay Interesting. I am only familiar with 2D CAs. With a 1D CA, you can generate each row with a for loop. I would start with a fixed number, like 10 generations for example. – Code-Apprentice Oct 09 '19 at 15:43
  • @Code-Apprentice thanks for the help, it's been very useful, but that's the problem, what i was trying to do is check all the cells of generation, than print it a than restart the process in the next generation, in the end result will be like the image, in this moment im studing the button method that you said, and i think that could do it right. From the time that i met CA i was facinated, and i think i will learn a lot with it, i making a final paper, i hope that i can explain well. thanks a lot for your help – Andre Dilay Oct 09 '19 at 19:39
  • @AndreDilay What I have in mind is something like this: create a new method named something like `drawAllGenerations()`. This has a loop that calls `rules.generate()` and then `drawCA()`. Now you call this `drawAllGenerations()` directly from `paintComponent()` instead of calling `drawCA()`. You will also need to modify `drawCA()` to adjust the y-coordinate of the cells that it draws. – Code-Apprentice Oct 09 '19 at 19:45
  • @Code-Apprentice That´s works, thanks a lot, i'll need do some adjustments to work properly, wow thanks a lot – Andre Dilay Oct 10 '19 at 15:00
  • @Code-Apprentice works as intended [Results Rule 30] (https://imgur.com/7w16eK5) thanks a lot – Andre Dilay Oct 10 '19 at 15:26
  • @AndreDilay Glad you got it to work. Note how I broke the problem down and described a solution in (mostly) English. This is often the first critical step in writing a computer program. Usually I write my steps as a bulleted or numbered list rather than in paragraph form. (For future notice, there shouldn't be a space between the `]` and the `(` to make a link in your comment.) – Code-Apprentice Oct 10 '19 at 15:59
  • @Code-Apprentice Thanks for the tips, i'll take note of these – Andre Dilay Oct 10 '19 at 19:11