Java 网格不准确';s单元坐标

Java 网格不准确';s单元坐标,java,swing,awt,Java,Swing,Awt,使用swing和awt,我创建了一个网格。用户可以单击任何空单元格 将其标记为红细胞。网格由20 x 20个单元组成,每个单元32个像素 当用户点击一个单元格时,我得到鼠标点击的x和y坐标,并执行以下计算以找出哪个是选中的 单元格: 问题是,当我在单元格边缘(右边框或下边框)附近单击时,行和列变得不准确(错误),导致标记下一个单元格(右边框或下边框),而不是标记我正在单击的正确单元格 越接近网格的右/下边界,精度就越差 这是我绘制网格的方式: public class MainPanel ext

使用swing和awt,我创建了一个网格。用户可以单击任何空单元格 将其标记为红细胞。网格由20 x 20个单元组成,每个单元32个像素

当用户点击一个单元格时,我得到鼠标点击的x和y坐标,并执行以下计算以找出哪个是选中的 单元格:

问题是,当我在单元格边缘(右边框或下边框)附近单击时,行和列变得不准确(错误),导致标记下一个单元格(右边框或下边框),而不是标记我正在单击的正确单元格

越接近网格的右/下边界,精度就越差

这是我绘制网格的方式:

public class MainPanel extends JPanel {

// reference to the model
private Model model;

public MainPanel() {

    setPreferredSize(new Dimension(660, 660));

    // retrieve the model
    model = Controller.getController().getModel();

    // draw 
    repaint();

    // listen to mouse clicks
    addMouseListener(new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent e) {

            int mouseX = e.getX();
            int mouseY = e.getY();

            System.out.println("mouseX: " + mouseX + " mouseY: " + mouseY);

            // get the row and column clicked
            int row = mouseY / Model.NODE_SIZE;
            int col = mouseX / Model.NODE_SIZE;

            if(row > Model.BOARD_SIZE - 1 || col > Model.BOARD_SIZE - 1) { // avoid out of bounds
                return;
            }

            System.out.println("row: " + row + " col: " + col);

            Controller.getController().getModel().setTarget(col, row);

            repaint();
        }
    });
}

/** 
 * Custom painting codes on this JPanel 
 * Called by repaint()
 */
@Override
public void paintComponent(Graphics g) { 
    super.paintComponent(g);    // fills background
    setBackground(Color.WHITE); // sets background color

    // draw the tiles
    Node[][] nodes = model.getBoard();

    for(int i = 0; i < Model.BOARD_SIZE; i++) {
        for(int j = 0; j < Model.BOARD_SIZE; j++) {
            if(nodes[i][j].getNodeType() == NodeType.OBSTACLE) {
                g.setColor(Color.BLACK);
                g.fillRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
            }
            else if(nodes[i][j].getNodeType() == NodeType.SOURCE) {
                g.setColor(Color.GREEN);
                g.fillRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
            }
            else if(nodes[i][j].getNodeType() == NodeType.TARGET) {
                g.setColor(Color.RED);
                g.fillRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
            }
            else {
                g.setColor(Color.BLACK);
                g.drawRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
            }
        }
    }
}
public类主面板扩展了JPanel{
//参考模型
私有模型;
公共主面板(){
设置首选尺寸(新尺寸(660660));
//检索模型
model=Controller.getController().getModel();
//画
重新油漆();
//听鼠标点击
addMouseListener(新的MouseAdapter(){
@凌驾
公共无效mouseClicked(MouseEvent e){
int mouseX=e.getX();
int mouseY=e.getY();
System.out.println(“mouseX:+mouseX+”mouseY:+mouseY);
//单击行和列
int row=鼠标/Model.NODE\u大小;
int col=mouseX/Model.NODE\u SIZE;
如果(row>Model.BOARD_SIZE-1 | | col>Model.BOARD_SIZE-1){//避免越界
返回;
}
System.out.println(“行:+row+”列:+col”);
Controller.getController().getModel().setTarget(列,行);
重新油漆();
}
});
}
/** 
*此JPanel上的自定义绘画代码
*由repaint()调用
*/
@凌驾
公共组件(图形g){
super.paintComponent(g);//填充背景
setBackground(Color.WHITE);//设置背景色
//画瓷砖
节点[][]节点=model.getBoard();
对于(int i=0;i
}

链接到runnable:

查看此代码:

g.fillRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
int row = mouseY / Model.NODE_SIZE;
int col = mouseX / Model.NODE_SIZE;
结合本规范:

g.fillRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
int row = mouseY / Model.NODE_SIZE;
int col = mouseX / Model.NODE_SIZE;
可疑,您在屏幕上绘制的矩形的大小为
i+Model.NODE_size*i
-因此屏幕上的矩形的大小在前面的每个矩形中偏移1。这个偏移会使你所选择的矩形的基本“检测”变得更加复杂,你点击屏幕的右下角越远,效果就越差

我怀疑如果你把密码改成

g.fillRect(Model.NODE_SIZE * i, Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
它将按预期工作。

查看此代码:

g.fillRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
int row = mouseY / Model.NODE_SIZE;
int col = mouseX / Model.NODE_SIZE;
结合本规范:

g.fillRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
int row = mouseY / Model.NODE_SIZE;
int col = mouseX / Model.NODE_SIZE;
可疑,您在屏幕上绘制的矩形的大小为
i+Model.NODE_size*i
-因此屏幕上的矩形的大小在前面的每个矩形中偏移1。这个偏移会使你所选择的矩形的基本“检测”变得更加复杂,你点击屏幕的右下角越远,效果就越差

我怀疑如果你把密码改成

g.fillRect(Model.NODE_SIZE * i, Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);

它将按预期工作。

您的绘制代码基本上是错误的

g.drawRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
将每个单元格的大小增加一个已绘制行/单元格的系数,例如

绿线通过使用
g.drawRect(0,0,线路板尺寸*节点尺寸,线路板尺寸*节点尺寸)计算得出,它应该是网格的可见区域,但您正在绘制超出它的区域

相反,如果我使用

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

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

    public static class MainPanel extends JPanel {

        public static final int NODE_SIZE = 32;
        public static final int BOARD_SIZE = 8;

        private int row, col = -1;

        public MainPanel() {

            // listen to mouse clicks
            addMouseListener(new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {

                    int mouseX = e.getX();
                    int mouseY = e.getY();

                    System.out.println("mouseX: " + mouseX + " mouseY: " + mouseY);

                    // get the row and column clicked
                    int row = mouseY / NODE_SIZE;
                    int col = mouseX / NODE_SIZE;

                    if (row > BOARD_SIZE - 1 || col > BOARD_SIZE - 1) { // avoid out of bounds
                        return;
                    }

                    System.out.println("row: " + row + " col: " + col);

                    repaint();
                }
            });

            addMouseMotionListener(new MouseAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    int mouseX = e.getX();
                    int mouseY = e.getY();
                    row = mouseY / NODE_SIZE;
                    col = mouseX / NODE_SIZE;
                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(BOARD_SIZE * NODE_SIZE, BOARD_SIZE * NODE_SIZE);
        }

        /**
         * Custom painting codes on this JPanel Called by repaint()
         */
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);    // fills background
            setBackground(Color.WHITE); // sets background color

            g.setColor(Color.GREEN);

            for (int i = 0; i < BOARD_SIZE; i++) {
                for (int j = 0; j < BOARD_SIZE; j++) {
                    if (row == j && col == i) {
                        g.setColor(Color.RED);
                        g.fillRect(NODE_SIZE * i, NODE_SIZE * j, NODE_SIZE, NODE_SIZE);
                    }
                    g.setColor(Color.BLACK);
                    g.drawRect(NODE_SIZE * i, NODE_SIZE * j, NODE_SIZE, NODE_SIZE);
                }
            }
        }
    }
}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(新的主面板());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共静态类主面板扩展了JPanel{
公共静态最终int节点_SIZE=32;
公共静态最终int板尺寸=8;
私有整数行,列=-1;
公共主面板(){
//听鼠标点击
addMouseListener(新密苏里州)