如何用网格布局填充JPanel的可交互正方形



我正在尝试用Java制作一个Snake Game版本,该版本使用JFrame+JPanel组合,其中JPanel包含全黑背景,绘制一个带有白色轮廓的正方形网格(drawRect(,并用深灰色(fillRect(填充,每个宽度和高度都是5 x 5。但是,当将每个节点/正方形添加到面板网格布局时,运行该程序根本不会显示窗口。只有在注释掉initNodes函数之后,它才会显示一个黑色背景的窗口。如何在JPanel网格布局中制作可交互的正方形?

Board.java

package snakegame;
import java.awt.Color;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Board {
JFrame window;
JPanel panel;
Graphics g;
protected final Node[][] nodes = new Node[800][1000];
protected static int WINDOW_WIDTH = 1000;
protected static int WINDOW_HEIGHT = 800;
public Board(){
initBoard();
}
private void initPanel(){
panel = new JPanel();
panel.setBackground(Color.BLACK);
panel.setLayout(new GridLayout(800,1000));
initNodes();
window.getContentPane().add(panel);
}
private void initNodes(){
for(int row = 0; row < nodes.length; row++){
for(int col = 0; col < nodes[row].length; col++){
nodes[row][col] = new Node(row, col); //Whenever this is called this should draw a square at each node
panel.add(nodes[row][col]); //Add to panel grid layout
}
}
}
private void initBoard(){
window = new JFrame();
window.setTitle("JSnake!");
window.setSize(WINDOW_WIDTH,WINDOW_HEIGHT);
window.setResizable(false);
window.setLocationRelativeTo(null);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initPanel();
window.pack();
window.setVisible(true);
}
}

Node.java

package snakegame;
import javax.swing.*;
import java.awt.Color;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Node extends JPanel {
int xPos;
int yPos;
public Node(int x, int  y){
this.xPos = x;
this.yPos = y;
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.WHITE);
g2.drawRect(this.xPos,this.yPos, Board.WINDOW_WIDTH/200,Board.WINDOW_HEIGHT/ 160);
g2.setColor(Color.DARK_GRAY);
g2.fillRect(this.xPos,this.yPos,Board.WINDOW_WIDTH/200,Board.WINDOW_HEIGHT/ 160);
}
}

经过大量的实验,我决定放弃这个项目,制作一个全新的版本,在我看来,这个版本更有组织性,总共有4个文件。我想补充一点,游戏本身还没有完成,因为这不是我的问题,相反,它是在问如何为使用JPanel+JFrame制作一个合适的网格布局(因此,你会看到这么多将被删除的导入语句(,下面是我的解决方案:

Main.java:

package snakegame;
import java.awt.EventQueue;
public class Main {
public static void main(String arg[]){
EventQueue.invokeLater(() -> {
var gameFrame = new GameFrame();
gameFrame.window.setVisible(true);
});
}
}

GameFrame.java:

package snakegame;
import javax.swing.*;
import java.awt.*;
public class GameFrame {
JFrame window;
Game panel;
public GameFrame(){
window = new JFrame();
panel = new Game();
window.setUndecorated(false);
window.setLocationRelativeTo(null);
window.setTitle("JSnake");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
window.add(panel);
window.pack();
window.setVisible(true);
}
}

Node.java:

package snakegame;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Node extends JPanel {
private final int SIZE = 20;
public Node(){
this.setBorder(BorderFactory.createLineBorder(Color.BLACK));
this.setPreferredSize(new Dimension(SIZE,SIZE));
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0,0, getWidth(), getHeight());
}
}

Game.java:


import java.awt.Color;
import java.awt.Image;
import java.awt.*;
import java.awt.event.*;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.ImageIcon;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.JMenu;
public class Game extends JPanel implements ActionListener {
private final int DELAY = 75;
private Node[][] grid = new Node[40][40];
private char direction;
Timer timer;
public Game(){
this.setBackground(Color.black);
this.setFocusable(true);
startGame();
}
private void startGame(){
initNodes();
timer = new Timer(DELAY, this);
timer.start();
}
private JPanel initNodes(){
this.setLayout(new GridLayout(40,40,0,0));
for(int row = 0; row <= grid.length - 1; row++){
for(int col = 0; col <= grid[row].length - 1; col++){
grid[row][col] = new Node();
this.add(grid[row][col]);
}
}
return this;
}
//Create the game loop
@Override
public void actionPerformed(ActionEvent e) {
}
//Check for key presses to use in the moveSnake method
public class KeyListener extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (direction != 'R') {
direction = 'L';
}
break;
case KeyEvent.VK_RIGHT:
if (direction != 'L') {
direction = 'R';
}
break;
case KeyEvent.VK_UP:
if (direction != 'D') {
direction = 'U';
}
break;
case KeyEvent.VK_DOWN:
if (direction != 'U') {
direction = 'D';
}
break;
}
}
}
}

相关内容

  • 没有找到相关文章

最新更新