0

I'm trying to change the background of a JPanel inside of a JFrame. JFrame consist of JPanels much like a grid. I"m trying to change a random JPanel inside of the JFrame and see the color change on each pass through the loop. Here is what I've got so far.

private static JPanel panel;
private static int index;

public static void main(String[] args)
{
    JFrame window = new JFrame();
    window. setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
    window.setSize(600, 600);
    GridLayout layout = new GridLayout(50, 50, 3, 3);
    panel = new JPanel(layout);
    panel.setSize(600, 600);

    //Initialize the JFrame with JPanels that
    //are all white.
    InitializeGrid(panel);

    window.add(panel);
    window.validate();
    window.setVisible(true);


    MainLoop();
}

private static void MainLoop()
{

      Component[] componentArrayTwo = panel.getComponents();

      int index = 0;

      while(true)
      {
        JPanel currentPanel = (JPanel) componentArrayTwo[index];
            currentPanel.setBackground(Color.GREEN);
            index++;

          if(index == 1600)
          {
              //Restart again
              index = 0;
          }

          //Colors everything back to white.
          Reset();
      }    
}

private static void InitializeGrid(JPanel panel)
{
      //40 x 40 = 1600
    for(int i = 0; i < 1600; i++)
    {
        JPanel cellPanel = new JPanel();

        cellPanel.setMinimumSize(new Dimension(3, 3));
        cellPanel.setMaximumSize(new Dimension(3, 3));
        cellPanel.setPreferredSize(new Dimension(3, 3));
        cellPanel.setBackground(Color.WHITE);

        panel.add(cellPanel);
    }
}

/*************************************************************************/
//NAME: Reset
//DESCRIPTION: Resets all the cells back to white which is executed on
//each iteration through the loop.
/*************************************************************************/
private static void Reset()
{
    Component[] componentArrayTwo = panel.getComponents();

    for(Component individualComponent : componentArrayTwo ) 
    {
        JPanel panelToColor = (JPanel) individualComponent;


        panelToColor.setBackground(Color.WHITE);

    }
}

If I uncomment line the panel.add(individualPanel) this will show the color change, but it keeps adding more and more JPanels to the JFrame. However, commenting this line lets me change the color but doesn't show any changes in the JFrame. I've tried changing various pieces in this code but so far I've been unsuccessful. What should happen is that on each pass through the loop I should see a Green JPanel show up in random spots in the JFrame. If anyone could help I'd appreciate it.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
zic10
  • 2,310
  • 5
  • 30
  • 55
  • Look into using a `javax.swing.Timer` if you're looking for animation. See the bottom of [this answer](http://stackoverflow.com/a/21971382/2587435) for some examples. – Paul Samsotha Feb 27 '14 at 17:41

1 Answers1

4

Use a javax.swing.Timer if you want to animate with swing. See How to use Swing Timers

See more examples here and here and here and here.

Test this one out. It changes the background of just one panel, instead of trying to use multiple ones like you are trying to do.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class ColorChange extends JPanel {

    private static final int D_W = 300;
    private static final int D_H = 300;

    private final List<Color> colors;
    private final Random random;
    private Color bgColor = Color.BLUE;

    public ColorChange() {
        colors = createColorList();
        random = new Random();

        Timer timer = new Timer(500, new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                int index = random.nextInt(colors.size());
                bgColor = colors.get(index);
                repaint();
            }
        });
        timer.start();
    }

    private List<Color> createColorList() {
        List<Color> list = new ArrayList<>();
        list.add(Color.BLUE);
        list.add(Color.CYAN);
        list.add(Color.PINK);
        list.add(Color.ORANGE);
        list.add(Color.MAGENTA);
        list.add(Color.GREEN);
        list.add(Color.YELLOW);
        list.add(Color.RED);
        list.add(Color.GRAY);
        return list;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(bgColor);
        g.fillRect(0, 0, getWidth(), getHeight());
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(D_W, D_H);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new ColorChange());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}
Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thank you for you code. This helps a lot and I've been playing with it. However, I need to have the capability of changing multiple panels in the JFrame. I'm basically trying to represent a 2x2 array where the array cells are the JPanels and I need the capability of coloring any of them. A timer as you said may be what I need because setBackgroundColor is called too quickly. In essence I need to draw a grid, handle a set of rules, and redraw it entirely showing changes that were caused from the rule set. – zic10 Feb 28 '14 at 03:44
  • So do you want them all visible at the same time? I don't get what you're trying to do. And what rule? – Paul Samsotha Feb 28 '14 at 03:47
  • I've posted my updated code. Basically if you comment out the Reset() method call in the MainLoop() method you can see the grid being drawn. However the speed at which it is drawn is very fast. The rules are for a game of life implementation. Basically every cell in the array can be affected by neighbor cells. This causes their colors to change, hence why I need to be able to change colors for any given cell on one pass through the loop. – zic10 Feb 28 '14 at 04:04
  • Yea I'm not familiar with the game of life. And I still don't get what is supposed to happen. Just focus on one specific question. And try your best to exaplain what is supposed to happen and what currently is happening and what code is causing this. – Paul Samsotha Feb 28 '14 at 04:40
  • I don't get why so many panels. Are you just trying to animate pixel colors? – Paul Samsotha Feb 28 '14 at 04:44
  • Trying to change panel colors just the wya it is being done in this link: http://stackoverflow.com/questions/12710390/drawing-a-grid-on-a-picturebox – zic10 Feb 28 '14 at 17:11
  • I figured the changing colors part, but what exactly triggers them to change and how do you want them animated (because you said the way you have it is too fast. The reason I want to know is so I can maybe come up with an example, if I can't figure out your code. – Paul Samsotha Feb 28 '14 at 17:14
  • Change will be triggered based on the game of life rules. The simplest explanation would be that cells change colors based on the color or properties of their neighbor cells. Therefore I'm trying to evaluate every cell in one pass through the loop iteratively and look at the cell's neighbor cells and change colors and then redraw the grid. Heres a visual: https://www.youtube.com/watch?v=OfoYxIyE4Sk – zic10 Feb 28 '14 at 17:17
  • Can you post a running program so I can see where you're at with it – Paul Samsotha Feb 28 '14 at 17:25
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/48707/discussion-between-zic10-and-peeskillet) – zic10 Feb 28 '14 at 17:29