使用swing和awt我创建了一个网格。用户可以单击任何空单元格 网格,标记为红色单元格。网格由20 x 20个单元组成,每个单元32个像素。
当用户点击单元格时,我会获得鼠标单击的x和y坐标,然后执行以下计算以找出所选的 细胞:
int mouseX = e.getX();
int mouseY = e.getY();
int row = mouseY / Model.NODE_SIZE;
int col = mouseX / Model.NODE_SIZE;
问题是当我在单元格的边缘(右边框或底部边框)附近点击时,行和列不准确(错误),导致下一个单元格的标记(单元格向右或单元格到底部)而不是我正在点击的正确标记。
我越接近网格的右/下边界,精度就越差。
这是我绘制网格的方式:
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);
}
}
}
}
}
链接到runnable:
https://www.dropbox.com/s/bqoimipp7i1f39s/GridExample.jar?dl=0
答案 0 :(得分:4)
你的油漆代码错了,基本上......
g.drawRect(i + Model.NODE_SIZE * i, j + Model.NODE_SIZE * j, Model.NODE_SIZE, Model.NODE_SIZE);
将每个单元格的大小增加一个行/单元格的因子,例如......
绿线是使用g.drawRect(0, 0, BOARD_SIZE * NODE_SIZE, BOARD_SIZE * NODE_SIZE);
计算的,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);
}
}
}
}
}
应该是网格的可见区域,但是你要超越它。
相反,如果我使用......
Rectangle
它变得更加准确..
另一个想法可能是使用Rectangle#contains
来定义网格的每个单元格,这样你就可以使用Str.split_delim (Str.regexp " ") "this is my sentence";;
- : bytes list = ["this"; "is"; "my"; "sentence"]
来测试鼠标是否在任何给定的单元格范围内......作为一个想法
答案 1 :(得分:3)
看到这段代码:
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);
它将按预期工作。