Home > Software design >  How to convert a point on screen into indices of the corresponding object in a 2d-array
How to convert a point on screen into indices of the corresponding object in a 2d-array

Time:04-15

I have a 2d-array of Rectangle-objects which make up a grid in JPanel. I want to make a method which will take x and y coordinates of a MouseEvent as parameters and return the indices of the corresponding Rectangle in that array. Let's say every Rectangle in that array has the area of 30x30 pixels and we have a point at x = 36, y = 15. The result in this case should be indexX = 1 and indexY = 0. All I need is a formula which would calculate it.

Edit: I made a simplified version of my problem:

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

public class Grid extends JPanel {
    private final Rectangle[][] grid = new Rectangle[10][10];

    public Grid() {
        this.setSize(300, 300);
        for (int i = 0; i < 10; i  ) {
            for (int j = 0; j < 10; j  ) {
                grid[i][j] = new Rectangle(i * getWidth() / 10, j * getHeight() / 10, 30, 30);
            }
        }
        this.setVisible(true);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i = 0; i < 10; i  ) {
            for (int j = 0; j < 10; j  ) {
                g.setColor(Color.BLUE);
                g.fillRect((int) grid[i][j].getX(), (int) grid[i][j].getY(), (int) grid[i][j].getWidth(), (int) grid[i][j].getHeight());
            }
        }


    }

    public static Point mousePositionToRectangleIndex(int xPos, int yPos) {
        //Problem:
        //int indexX = formulaHere;
        //int indexY = formulaHere;
        // return new Point(indexX, indexY);
        return null;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        Grid grid = new Grid();
        MouseMotionListener mml = new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent e) {
                mousePositionToRectangleIndex(e.getX(), e.getY());
            }

            @Override
            public void mouseMoved(MouseEvent e) {

            }
        };
        frame.addMouseMotionListener(mml);
        frame.add(grid);
        frame.setSize(300, 300);
        frame.setVisible(true);
    }
}

All I need is the formula for mousePositionToRectangleIndex()

CodePudding user response:

You can simply check which rectangle has been pressed in your mouse listener to find out your i and j. For example:

  1. give the grid JPanel a preferred size, not a size:
    public Grid() {
        // this.setSize(300, 300);
        setPreferredSize(new Dimension(300, 300));
        for (int i = 0; i < 10; i  ) {
            for (int j = 0; j < 10; j  ) {
                grid[i][j] = new Rectangle((i * getPreferredSize().width) / 10, (j * getPreferredSize().height) / 10, 30, 30);
            }
        }
        
        addMouseListener(new MyMouse());
    }
  1. give it a MouseListener that checks if a rectangle contains the click point:
    private class MyMouse extends MouseAdapter {
        @Override
        public void mousePressed(MouseEvent e) {
            for (int i = 0; i < grid.length; i  ) {
                for (int j = 0; j < grid[i].length; j  ) {
                    if (grid[i][j].contains(e.getPoint())) {
                        System.out.printf("Point pressed, i, j: [%d, %d]%n", i, j);
                    }
                }
            }
        }
    }
  1. Don't set the JFrame's size (you're forgetting the menu bar takes space, but rather pack it:
        frame.add(grid);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // frame.setSize(300, 300);
        frame.pack();
        frame.setVisible(true);

For example:

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

public class Grid extends JPanel {
    private final Rectangle[][] grid = new Rectangle[10][10];

    public Grid() {
        // this.setSize(300, 300);
        setPreferredSize(new Dimension(300, 300));
        for (int i = 0; i < 10; i  ) {
            for (int j = 0; j < 10; j  ) {
                grid[i][j] = new Rectangle((i * getPreferredSize().width) / 10, (j * getPreferredSize().height) / 10, 30, 30);
            }
        }
        
        addMouseListener(new MyMouse());
    }
    
    private class MyMouse extends MouseAdapter {
        @Override
        public void mousePressed(MouseEvent e) {
            for (int i = 0; i < grid.length; i  ) {
                for (int j = 0; j < grid[i].length; j  ) {
                    if (grid[i][j].contains(e.getPoint())) {
                        System.out.printf("Point pressed, i, j: [%d, %d]%n", i, j);
                    }
                }
            }
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        for (int i = 0; i < 10; i  ) {
            for (int j = 0; j < 10; j  ) {
                g2.setColor(Color.BLUE);
                // g.fillRect((int) grid[i][j].getX(), (int) grid[i][j].getY(), (int) grid[i][j].getWidth(), (int) grid[i][j].getHeight());
                g2.fill(grid[i][j]);
            }
        }


    }

    public static Point mousePositionToRectangleIndex(int xPos, int yPos) {
        //Problem:
        //int indexX = formulaHere;
        //int indexY = formulaHere;
        // return new Point(indexX, indexY);
        return null;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        Grid grid = new Grid();
        MouseMotionListener mml = new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent e) {
                mousePositionToRectangleIndex(e.getX(), e.getY());
            }

            @Override
            public void mouseMoved(MouseEvent e) {

            }
        };
        // frame.addMouseMotionListener(mml);
        frame.add(grid);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // frame.setSize(300, 300);
        frame.pack();
        frame.setVisible(true);
    }
}

But having said that, the whole thing can be done with a JLabel grid, and perhaps a little more cleanly too. Here I increment the color of the clicked cell:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

public class Grid2 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            GridPanel mainPanel = new GridPanel();

            JFrame frame = new JFrame("GUI");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }

}

@SuppressWarnings("serial")
class GridPanel extends JPanel {
    private static final int SIDES = 10;
    private static final int MAX_COLORS = 6;
    private static final Dimension LABEL_SIZE = new Dimension(30, 30);
    private int[][] model = new int[SIDES][SIDES];
    private JLabel[][] labelGrid = new JLabel[SIDES][SIDES];
    private List<Color> colors = new ArrayList<>();
    
    public GridPanel() {
        for (int i = 0; i < MAX_COLORS; i  ) {
            float hue = ((float) i) / MAX_COLORS;
            Color c = Color.getHSBColor(hue, 1f, 1f);
            colors.add(c);
        }
        setLayout(new GridLayout(SIDES, SIDES));
        for (int i = 0; i < labelGrid.length; i  ) {
            for (int j = 0; j < labelGrid[i].length; j  ) {
                model[i][j] = 0;
                JLabel label = new JLabel();
                label.setPreferredSize(LABEL_SIZE);
                label.setOpaque(true);
                label.setBackground(colors.get(0));
                label.addMouseListener(new MyMouse(i, j));
                labelGrid[i][j] = label;
                add(label);
            }
        }
    }
    
    private class MyMouse extends MouseAdapter {
        private int i;
        private int j;
        
        public MyMouse(int i, int j) {
            this.i = i;
            this.j = j;
        }

        @Override
        public void mousePressed(MouseEvent e) {
            System.out.printf("Point pressed, i, j: [%d, %d]%n", i, j);
            model[i][j]  ;
            model[i][j] %= MAX_COLORS;
            labelGrid[i][j].setBackground(colors.get(model[i][j]));
        }
    }   
}
  • Related