如何将屏幕上的点转换为二维数组中相应对象的索引

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

我有一个二维矩形对象数组,它们在 JPanel 中构成一个网格。我想制作一个方法,它将 MouseEvent 的 x 和 y 坐标作为参数,return 该数组中相应 Rectangle 的索引。假设该数组中的每个矩形都有 30x30 像素的面积,我们在 x = 36,y = 15 处有一个点。在这种情况下,结果应该是 indexX = 1 和 indexY = 0。我只需要一个公式计算一下。

编辑:我做了一个简化版的问题:

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);
    }
}

我只需要 mousePositionToRectangleIndex() 的公式

您可以简单地检查鼠标侦听器中按下了哪个矩形以找出您的 i 和 j。例如:

  1. 为网格 JPanel 指定一个首选大小,而不是大小:
    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. 给它一个 MouseListener 检查矩形是否包含点击点:
    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. 不要设置 JFrame 的大小(您忘记了菜单栏需要 space,而是将其打包:
        frame.add(grid);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // frame.setSize(300, 300);
        frame.pack();
        frame.setVisible(true);

例如:

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);
    }
}

不过话说回来,整个事情都可以用 JLabel 网格来完成,而且也许还更干净一些。这里我增加了点击单元格的颜色:

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]));
        }
    }   
}