二维网格不适合路径可视化工具的 JFrame
2D grid is not fitting in JFrame for pathing visualizer
我正在尝试创建一个二维网格,其节点大小取决于框架 height/width 的大小,但是每当我 运行 程序时,底行和右列都会被剪掉离开。这是我的执行代码:
public class PathfindingVisualizer {
public static void main(String[] args) {
Grid grid = new Grid(10,10, new Dimension(1000, 1000));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GridFrame(grid);
}
});
}
}
这是网格 class:
package gui;
import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
public class Grid extends JPanel {
private final int rows, cols;
private final Node[][] grid;
private Node start, end;
private final Dimension size;
private int nodeSize;
public Grid(int rows, int cols, Dimension size) {
this.rows = rows;
this.cols = cols;
this.grid = new Node[cols][rows];
this.size = size;
this.nodeSize = getWidth() / cols;
initializeGrid();
}
public void initializeGrid() {
// populate grid as a 2D array of Nodes
for (int col=0; col<cols; col++) {
for (int row=0; row<rows; row++) {
grid[col][row] = new Node(col, row);
}
}
// create neighbors for all the Nodes
for (int col=0; col<cols; col++) {
for (int row=0; row<rows; row++) {
setNeighbors(col, row);
}
}
// create start and end points for pathfinding
start = grid[0][0];
end = grid[cols-1][rows-1];
}
private void setNeighbors(int col, int row) {
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (int[] direction : directions) {
int neighborCol = direction[0] + col;
int neighborRow = direction[1] + row;
if (neighborCol >= 0 && neighborCol < cols &&
neighborRow >= 0 && neighborRow < rows) {
if (Arrays.equals(direction, new int[]{1, 0})) {
grid[col][row].setDown(grid[neighborCol][neighborRow]);
}
if (Arrays.equals(direction, new int[]{-1, 0})) {
grid[col][row].setUp(grid[neighborCol][neighborRow]);
}
if (Arrays.equals(direction, new int[]{0, 1})) {
grid[col][row].setRight(grid[neighborCol][neighborRow]);
}
if (Arrays.equals(direction, new int[]{0, -1})) {
grid[col][row].setLeft(grid[neighborCol][neighborRow]);
}
}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
for (int col=0; col<cols; col++) {
for (int row=0; row<rows; row++) {
g.drawRect(col*nodeSize, row*nodeSize, nodeSize, nodeSize);
}
}
}
public int getRows() {
return rows;
}
public int getCols() {
return cols;
}
public Node[][] getGrid() {
return grid;
}
@Override
public Dimension getSize() {
return size;
}
public int getHeight(){
return (int) size.getHeight();
}
public int getWidth(){
return (int) size.getWidth();
}
}
这是 GridFrame class:
package gui;
import javax.swing.*;
import java.awt.*;
public class GridFrame {
public GridFrame(Grid grid) {
JFrame frame = new JFrame("Pathfinding Visualizer");
frame.setPreferredSize(grid.getSize());
frame.setContentPane(grid);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
我也一直在搞乱具有绘图功能的实现 w/in 节点 class 但到目前为止还没有任何运气。
这里的目标是制作一个路径可视化工具。这是我的第一个 Java 项目,所以任何帮助都是有帮助的!
编辑:
这也是节点 class:
package gui;
public class Node {
private final int row, col;
private Node up, down, left, right;
private boolean start, end, wall, visited;
public Node(int col, int row) {
this.col = col;
this.row = row;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public Node getUp() {
return up;
}
public void setUp(Node up) {
this.up = up;
}
public Node getDown() {
return down;
}
public void setDown(Node down) {
this.down = down;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public boolean isStart() {
return start;
}
public void setStart(boolean start) {
this.start = start;
}
public boolean isEnd() {
return end;
}
public void setEnd(boolean end) {
this.end = end;
}
public boolean isWall() {
return wall;
}
public void setWall(boolean wall) {
this.wall = wall;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
}
让我们从……开始吧
Grid grid = new Grid(10,10, new Dimension(1000, 1000));
public Grid(int rows, int cols, Dimension size) {
this.rows = rows;
this.cols = cols;
this.grid = new Node[cols][rows];
this.size = size;
this.nodeSize = getWidth() / cols;
initializeGrid();
}
像这样将 Dimension
传递到构造函数中是个坏主意,除了您完全忽略高度这一事实之外,您最终可能会截断整数(getWidth() / cols
会很简单截取小数值并且不会应用任何类型的舍入,这可能会给您带来错误的结果)
接下来你做...
this.nodeSize = getWidth() / cols;
在正常情况下,getWidth
此时会 return 0
,除非你...
@Override
public Dimension getSize() {
return size;
}
public int getHeight() {
return (int) size.getHeight();
}
public int getWidth() {
return (int) size.getWidth();
}
这是非常值得怀疑的(而且根本不推荐)。还记得我讲过“整数截断”吗?这可能意味着组件的大小是 bigger/small 那么整个网格的实际面积。也不建议覆盖 getSize
,因为您会弄乱布局管理系统,这可能会产生无穷无尽的长期问题。
最后,你的问题的关键是...
frame.setPreferredSize(grid.getSize());
你似乎没有意识到的是,可视内容大小是frame size
- window decorations
,这使得你的程序的可视区域<1000x1000
那么,答案是什么?改为传递单个单元格的大小...
private int cellSize;
public Grid(int rows, int cols, int cellSize) {
this.rows = rows;
this.cols = cols;
this.grid = new String[cols][rows];
this.cellSize = cellSize;
initializeGrid();
}
并覆盖 getPreferredSize
(而不是 getSize
)...
@Override
public Dimension getPreferredSize() {
return new Dimension(cellSize * cols, cellSize * rows);
}
显然 paintComponent
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
g.drawRect(col * cellSize, row * cellSize, cellSize, cellSize);
}
}
}
并摆脱
frame.setPreferredSize(grid.getSize());
可运行示例...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new Grid(10, 10, 100));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Grid extends JPanel {
private final int rows, cols;
private final String[][] grid;
private int cellSize;
public Grid(int rows, int cols, int cellSize) {
this.rows = rows;
this.cols = cols;
this.grid = new String[cols][rows];
this.cellSize = cellSize;
initializeGrid();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(cellSize * cols, cellSize * rows);
}
public void initializeGrid() {
// populate grid as a 2D array of Nodes
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
grid[col][row] = col + "x" + row;
}
}
// create neighbors for all the Nodes
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
setNeighbors(col, row);
}
}
// create start and end points for pathfinding
//start = grid[0][0];
//end = grid[cols - 1][rows - 1];
}
private void setNeighbors(int col, int row) {
//int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
//
//for (int[] direction : directions) {
// int neighborCol = direction[0] + col;
// int neighborRow = direction[1] + row;
//
// if (neighborCol >= 0 && neighborCol < cols
// && neighborRow >= 0 && neighborRow < rows) {
// if (Arrays.equals(direction, new int[]{1, 0})) {
// grid[col][row].setDown(grid[neighborCol][neighborRow]);
// }
// if (Arrays.equals(direction, new int[]{-1, 0})) {
// grid[col][row].setUp(grid[neighborCol][neighborRow]);
// }
// if (Arrays.equals(direction, new int[]{0, 1})) {
// grid[col][row].setRight(grid[neighborCol][neighborRow]);
// }
// if (Arrays.equals(direction, new int[]{0, -1})) {
// grid[col][row].setLeft(grid[neighborCol][neighborRow]);
// }
// }
//}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
g.drawRect(col * cellSize, row * cellSize, cellSize, cellSize);
}
}
}
public int getRows() {
return rows;
}
public int getCols() {
return cols;
}
//public Node[][] getGrid() {
// return grid;
//}
}
}
我正在尝试创建一个二维网格,其节点大小取决于框架 height/width 的大小,但是每当我 运行 程序时,底行和右列都会被剪掉离开。这是我的执行代码:
public class PathfindingVisualizer {
public static void main(String[] args) {
Grid grid = new Grid(10,10, new Dimension(1000, 1000));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GridFrame(grid);
}
});
}
}
这是网格 class:
package gui;
import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
public class Grid extends JPanel {
private final int rows, cols;
private final Node[][] grid;
private Node start, end;
private final Dimension size;
private int nodeSize;
public Grid(int rows, int cols, Dimension size) {
this.rows = rows;
this.cols = cols;
this.grid = new Node[cols][rows];
this.size = size;
this.nodeSize = getWidth() / cols;
initializeGrid();
}
public void initializeGrid() {
// populate grid as a 2D array of Nodes
for (int col=0; col<cols; col++) {
for (int row=0; row<rows; row++) {
grid[col][row] = new Node(col, row);
}
}
// create neighbors for all the Nodes
for (int col=0; col<cols; col++) {
for (int row=0; row<rows; row++) {
setNeighbors(col, row);
}
}
// create start and end points for pathfinding
start = grid[0][0];
end = grid[cols-1][rows-1];
}
private void setNeighbors(int col, int row) {
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (int[] direction : directions) {
int neighborCol = direction[0] + col;
int neighborRow = direction[1] + row;
if (neighborCol >= 0 && neighborCol < cols &&
neighborRow >= 0 && neighborRow < rows) {
if (Arrays.equals(direction, new int[]{1, 0})) {
grid[col][row].setDown(grid[neighborCol][neighborRow]);
}
if (Arrays.equals(direction, new int[]{-1, 0})) {
grid[col][row].setUp(grid[neighborCol][neighborRow]);
}
if (Arrays.equals(direction, new int[]{0, 1})) {
grid[col][row].setRight(grid[neighborCol][neighborRow]);
}
if (Arrays.equals(direction, new int[]{0, -1})) {
grid[col][row].setLeft(grid[neighborCol][neighborRow]);
}
}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
for (int col=0; col<cols; col++) {
for (int row=0; row<rows; row++) {
g.drawRect(col*nodeSize, row*nodeSize, nodeSize, nodeSize);
}
}
}
public int getRows() {
return rows;
}
public int getCols() {
return cols;
}
public Node[][] getGrid() {
return grid;
}
@Override
public Dimension getSize() {
return size;
}
public int getHeight(){
return (int) size.getHeight();
}
public int getWidth(){
return (int) size.getWidth();
}
}
这是 GridFrame class:
package gui;
import javax.swing.*;
import java.awt.*;
public class GridFrame {
public GridFrame(Grid grid) {
JFrame frame = new JFrame("Pathfinding Visualizer");
frame.setPreferredSize(grid.getSize());
frame.setContentPane(grid);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
我也一直在搞乱具有绘图功能的实现 w/in 节点 class 但到目前为止还没有任何运气。
这里的目标是制作一个路径可视化工具。这是我的第一个 Java 项目,所以任何帮助都是有帮助的!
编辑: 这也是节点 class:
package gui;
public class Node {
private final int row, col;
private Node up, down, left, right;
private boolean start, end, wall, visited;
public Node(int col, int row) {
this.col = col;
this.row = row;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public Node getUp() {
return up;
}
public void setUp(Node up) {
this.up = up;
}
public Node getDown() {
return down;
}
public void setDown(Node down) {
this.down = down;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public boolean isStart() {
return start;
}
public void setStart(boolean start) {
this.start = start;
}
public boolean isEnd() {
return end;
}
public void setEnd(boolean end) {
this.end = end;
}
public boolean isWall() {
return wall;
}
public void setWall(boolean wall) {
this.wall = wall;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
}
让我们从……开始吧
Grid grid = new Grid(10,10, new Dimension(1000, 1000));
public Grid(int rows, int cols, Dimension size) {
this.rows = rows;
this.cols = cols;
this.grid = new Node[cols][rows];
this.size = size;
this.nodeSize = getWidth() / cols;
initializeGrid();
}
像这样将 Dimension
传递到构造函数中是个坏主意,除了您完全忽略高度这一事实之外,您最终可能会截断整数(getWidth() / cols
会很简单截取小数值并且不会应用任何类型的舍入,这可能会给您带来错误的结果)
接下来你做...
this.nodeSize = getWidth() / cols;
在正常情况下,getWidth
此时会 return 0
,除非你...
@Override
public Dimension getSize() {
return size;
}
public int getHeight() {
return (int) size.getHeight();
}
public int getWidth() {
return (int) size.getWidth();
}
这是非常值得怀疑的(而且根本不推荐)。还记得我讲过“整数截断”吗?这可能意味着组件的大小是 bigger/small 那么整个网格的实际面积。也不建议覆盖 getSize
,因为您会弄乱布局管理系统,这可能会产生无穷无尽的长期问题。
最后,你的问题的关键是...
frame.setPreferredSize(grid.getSize());
你似乎没有意识到的是,可视内容大小是frame size
- window decorations
,这使得你的程序的可视区域<1000x1000
那么,答案是什么?改为传递单个单元格的大小...
private int cellSize;
public Grid(int rows, int cols, int cellSize) {
this.rows = rows;
this.cols = cols;
this.grid = new String[cols][rows];
this.cellSize = cellSize;
initializeGrid();
}
并覆盖 getPreferredSize
(而不是 getSize
)...
@Override
public Dimension getPreferredSize() {
return new Dimension(cellSize * cols, cellSize * rows);
}
显然 paintComponent
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
g.drawRect(col * cellSize, row * cellSize, cellSize, cellSize);
}
}
}
并摆脱
frame.setPreferredSize(grid.getSize());
可运行示例...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new Grid(10, 10, 100));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Grid extends JPanel {
private final int rows, cols;
private final String[][] grid;
private int cellSize;
public Grid(int rows, int cols, int cellSize) {
this.rows = rows;
this.cols = cols;
this.grid = new String[cols][rows];
this.cellSize = cellSize;
initializeGrid();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(cellSize * cols, cellSize * rows);
}
public void initializeGrid() {
// populate grid as a 2D array of Nodes
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
grid[col][row] = col + "x" + row;
}
}
// create neighbors for all the Nodes
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
setNeighbors(col, row);
}
}
// create start and end points for pathfinding
//start = grid[0][0];
//end = grid[cols - 1][rows - 1];
}
private void setNeighbors(int col, int row) {
//int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
//
//for (int[] direction : directions) {
// int neighborCol = direction[0] + col;
// int neighborRow = direction[1] + row;
//
// if (neighborCol >= 0 && neighborCol < cols
// && neighborRow >= 0 && neighborRow < rows) {
// if (Arrays.equals(direction, new int[]{1, 0})) {
// grid[col][row].setDown(grid[neighborCol][neighborRow]);
// }
// if (Arrays.equals(direction, new int[]{-1, 0})) {
// grid[col][row].setUp(grid[neighborCol][neighborRow]);
// }
// if (Arrays.equals(direction, new int[]{0, 1})) {
// grid[col][row].setRight(grid[neighborCol][neighborRow]);
// }
// if (Arrays.equals(direction, new int[]{0, -1})) {
// grid[col][row].setLeft(grid[neighborCol][neighborRow]);
// }
// }
//}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
for (int col = 0; col < cols; col++) {
for (int row = 0; row < rows; row++) {
g.drawRect(col * cellSize, row * cellSize, cellSize, cellSize);
}
}
}
public int getRows() {
return rows;
}
public int getCols() {
return cols;
}
//public Node[][] getGrid() {
// return grid;
//}
}
}