Question

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.

Was it helpful?

Solution

  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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top