Home > Software design >  How to fill JPanel with Interact-able squares with a grid layout?
How to fill JPanel with Interact-able squares with a grid layout?

Time:08-11

I am trying to make a version of Snake Game in Java that uses a JFrame JPanel combination in which the JPanel contains an all black background and draws a grid of squares with a white outline (drawRect) and fill it with the color dark gray (fillRect) that are each 5 x 5 in width and height. However when adding each Node/Square to the panels gridLayout, running the program simply does not display the window at all. Only after commenting out the initNodes function does it display a window with a black background. How would I be able to make interact-able squares within a JPanel grid layout?

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

}

CodePudding user response:

After experimenting greatly, I decided to scrap that project and make a completely new version that in my opinion is much more organized and has 4 files in total, I would like to add that the game itself is not finished as that is not what my question was asking, rather it was asking how to make a proper grid layout for using JPanel JFrame (hence why you will see so many import statements that will be removed) and here is my solution:

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

    }
}
  • Related