1

I need to highlight different cells of a grid. In each iteration of my algorithm, a co-ordinate (i,j) is obtained. I pass these values to the Grid to the current_x and current_y variables. How do I color the corresponding cell by calling the paintComponent() method of the TestPane class.

public class Grid {

    int current_x;
    int current_y;

    public static void main(String[] args) {
        new Grid();
    }

    public Grid() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
             }
        });
    }

    public void getCurrentValues( int x, int y ){

        this.current_x = x;
        this.current_y = y;
    }

    public class TestPane extends JPanel {

        // code to create grid using rectangles

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            // more code
        }

    }
}

I am not clear as to how to pass the (i,j) values to the TestPane class and how to call the paintComponent.

Dinesh
  • 2,194
  • 3
  • 30
  • 52

1 Answers1

1
  1. Give TestPane setGridX(int x) and setGridY(int y) methods.
  2. Give any class that needs to call these methods a reference to the displayed TestPane instance.
  3. Call the methods when an event that triggers a change occurs. Then call repaint() on the TestPane instance.

Edit
New code that actually demonstrates my recommendations:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;

public class Grid {
   private static final int TIMER_DELAY = 200;
   private int current_x;
   private int current_y;
   private TestPane testPane = new TestPane();
   private Random random = new Random();

   public Grid() {
      EventQueue.invokeLater(new Runnable() {
         @Override
         public void run() {
            try {
               UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            }
            JFrame frame = new JFrame("Testing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new BorderLayout());
            // !! frame.add(new TestPane());
            frame.add(testPane); // !!
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
         }
      });
      new Timer(TIMER_DELAY, new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent evt) {
            current_x = random.nextInt(TestPane.MAX_X);
            current_y = random.nextInt(TestPane.MAX_Y);
            testPane.setGridX(current_x);
            testPane.setGridY(current_y);
            testPane.repaint();
         }
      }).start();
   }

   public void getCurrentValues(int x, int y) {
      this.current_x = x;
      this.current_y = y;
   }

   public static void main(String[] args) {
      new Grid();
   }
}

class TestPane extends JPanel {
   public static final int MAX_X = 8;
   public static final int MAX_Y = MAX_X;
   private static final int CELL_WIDTH = 50;
   private static final int PREF_W = CELL_WIDTH * MAX_X;
   private static final int PREF_H = CELL_WIDTH * MAX_Y;
   private static final Color FILL_COLOR = Color.yellow;
   private static final Color GRID_COLOR = Color.black;
   private int gridX = -1;
   private int gridY = -1;

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      for (int y = 0; y < MAX_Y; y++) {
         for (int x = 0; x < MAX_X; x++) {
            if (x == gridX && y == gridY) {
               g.setColor(FILL_COLOR);
               g.fillRect(x * CELL_WIDTH, y * CELL_WIDTH, CELL_WIDTH, CELL_WIDTH);
            }
            g.setColor(GRID_COLOR);
            g.drawRect(x * CELL_WIDTH, y * CELL_WIDTH, CELL_WIDTH, CELL_WIDTH);
         }
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public int getGridX() {
      return gridX;
   }

   public void setGridX(int gridX) {
      this.gridX = gridX;
   }

   public int getGridY() {
      return gridY;
   }

   public void setGridY(int gridY) {
      this.gridY = gridY;
   }
}

I am currently creating a TestPane object in the Grid class.

Yep, you definitely want to do this.

So should I create one in the main Driver class?

No, there should only be one TestPane instance. If it is needed in two locations, create it once, and pass it to the other via a method or constructor parameter.

Also, how should I trigger the calling of this repaint() method? I am not so clear still.

That all depends on what will trigger a change in your current_x and current_y values. You will likely need a listener of some sort, perhaps a MouseListener. In my example, I use an ActionListener held by a Swing Timer to randomly move the selected x and y values.


Edit 2
You state:

my trigger is - in each iteration of the algorithm - I get new (i,j) values.. so how so I incorporate that..

You would likely do the iteration in a background thread such as can be obtained with a SwingWorker object, and then call the TestPane's setGridX and setGridY method, and repaint.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • I am currently creating a TestPane object in the Grid class. So should I create one in the main `Driver` class? Also, how should I trigger the calling of this repaint() method? I am not so clear still. – Dinesh Feb 16 '14 at 23:10
  • @Dinesh: please check out my edited code above and run the program. I've tried to address each of your points above in an edit to my answer. – Hovercraft Full Of Eels Feb 16 '14 at 23:25
  • my trigger is - in each iteration of the algorithm - I get new (i,j) values.. so how so I incorporate that.. – Dinesh Feb 16 '14 at 23:32
  • @Dinesh: for this the key is to use a **background thread** such as can be obtained with a Swing Worker to do your iteration. – Hovercraft Full Of Eels Feb 16 '14 at 23:37
  • Can I just call the getCurrentValues() method in each iteration of my algorithm and update the values of testpane and call testpane.repaint? – Dinesh Feb 16 '14 at 23:41
  • I did what I mentioned in my previous comment and I am not sure if it works since the time for each iteration is very small- about 1000 iterations complete in a second. I am able to see a different cell highlighted but unable to see each step like an animation. What do you recommend? – Dinesh Feb 16 '14 at 23:51
  • @Dinesh: time to do some debugging to try to isolate the problem. If your iteration is doing 1000 iterations a second, perhaps you'd be better off not updating with each iteration, but perhaps after every 200 iterations. – Hovercraft Full Of Eels Feb 17 '14 at 00:24
  • I slowed down the computation to put the threads to sleep for 500ms and now I can see each step visually. Your solution also seems good. But I need to display each step. So I feel the approach of sleep is good enough for now - I just tried it now. Thanks for all the help! – Dinesh Feb 17 '14 at 00:33
  • Could you please answer this question of mine too :http://stackoverflow.com/questions/21817430/layout-using-java-swing/21817764?noredirect=1#21817764 – Dinesh Feb 17 '14 at 00:40
  • @Dinesh: Your question should be improved upon. You should create a [minimal, compilable, runnable, example program](http://stackoverflow.com/help/mcve), one that shows your best attempt to create the desired layout, but has no code unrelated to gui display, and you should post images of what you get and what you're trying to get. – Hovercraft Full Of Eels Feb 17 '14 at 00:42
  • I am not clear as to how to add a grid like what I create here to be incorporated in a layout. – Dinesh Feb 17 '14 at 01:06
  • @Dinesh: If you're still stuck, then please try to improve your question as per my suggestions. – Hovercraft Full Of Eels Feb 17 '14 at 01:35
  • You mean the other layout question- right? I am trying to use gridbaglayout and am getting errors. This is the first time I am using layouts so I might be having simple problems.. But I am stuck. Could you guide me as to how to post this? Actually I am confused. By the way, I do not know how to post images. – Dinesh Feb 17 '14 at 01:39
  • 1) first try to create the minimal program. Again, check [this link](http://stackoverflow.com/help/mcve). Note that this program should have no program logic, no ActionListeners, no changing grids, just components that are attempted to be laid out in an organized fashion. 2) If you're getting errors, post the errors, and indicate which line(s) is causing them. 3) to post images, create an image, and then when editing your question, post the image button above your edit window. 4) keep trying, don't give up. – Hovercraft Full Of Eels Feb 17 '14 at 01:46