Home > Enterprise >  How to make a grid of buttons
How to make a grid of buttons

Time:09-17

I'm studying Java these days, my first project is to create a "Go board", 9 * 9 rows and columns, and place black and white stones on the intersections.

I created a board with 9 * 9 lines and columns, now I have to create black and white stones using the JButton component.

Other than the color, size, and position of the button on the first row (setLayout), I was unable to turn the button into a circle and place the stone on the intersection points.

From multiple searches for related guides, I have noticed that there is some unique structure that I am not familiar with for creating and designing buttons.

And now my question comes in - what is the code structure I need to create in order to produce a button in the shape of a circle, size 65 * 65, in black or white? Do I need to create a new class for this? How and where should I integrate JPanel?

public class Main {

    public static void main(String[] args) {
        Board board = new Board(900, 900, "Go board");
    }
}

import java.awt.*;
import javax.swing.*;

public class Board extends JPanel {
    private int width;
    private int height;
    private String title;

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Board(int width, int height, String title) {
        super();
        this.width = width;
        this.height = height;
        this.title = title;
        this.initBoard();

    }

    public Board() {
        super();
    }

    public void initBoard() {
        JFrame f = new JFrame(this.getTitle());
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // f.getContentPane().setBackground(Color.getHSBColor(25, 75, 47));
        f.setSize(this.getWidth(), this.getHeight());
        // f.setLocation(550, 25);
        f.add(this, BorderLayout.CENTER);
        f.setVisible(true);

        JButton stone = new JButton("    ");
        f.add(stone);
        f.setLayout(new FlowLayout());
        stone.setBackground(Color.BLACK.darker());
        stone.setBorder(BorderFactory.createDashedBorder(getForeground()));
        stone.setPreferredSize(new Dimension(65, 65));

    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i = 0; i < 10; i  ) {
            g.drawLine(0, 10   (i * ((this.getWidth() - 20) / 9)), this.getWidth(),
                    10   (i * ((this.getWidth() - 20) / 9)));
            g.drawLine(10   (i * ((this.getHeight() - 20) / 9)), 0, 10   (i * ((this.getHeight() - 20) / 9)),
                    this.getHeight());
        }
    }
}

Before uploading the post, I read the following posts:

  • enter image description here



    Alternatively you can produce the board by custom painting of a JPanel. This will make the individual "stones" not clickable and more difficult to modify:

    import java.awt.*;
    import javax.swing.*;
    
    public class GridByPainting extends JPanel {
    
        private static final int ROWS = 9, COLS = 9, SIZE = 65, BORDER = 2;
        private static final Color BOARD_COLOR = Color.BLACK, STONE = Color.YELLOW,
                WHITE_STONE = Color.WHITE, BLACK_STONE = Color.BLACK;
        private final Dimension size;
    
        public GridByPainting() {
            int x = BORDER   COLS*(SIZE   BORDER);
            int y = BORDER   ROWS*(SIZE   BORDER);
            size = new Dimension(x,y);
            this.initBoard();
        }
    
        @Override
        public Dimension getPreferredSize() {
            return size;
        }
        public void initBoard() {
            JFrame f = new JFrame("Grid By Painting");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setLayout(new GridBagLayout());
            f.add(this);
            f.pack();
            f.setVisible(true);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            int width = getWidth(); int height = getHeight();
            int stoneWidth = (width - BORDER) / COLS  - BORDER;
            int stoneHeight = (height -BORDER)/ ROWS - BORDER ;
    
            //draw board
            g.setColor(BOARD_COLOR);
            g.fillRect(0, 0, width, height);
    
            boolean isBlack = true;
            //draw square stones
            for (int col = 0; col < COLS; col  ) {
                for (int row = 0; row < ROWS; row  ) {
                    int x = BORDER   col*(stoneWidth   BORDER);
                    int y = BORDER   row*(stoneHeight   BORDER);
                    g.setColor(STONE);
                    g.fillRect(x, y, stoneWidth, stoneHeight);
                    //draw circle
                    g.setColor(isBlack ? BLACK_STONE : WHITE_STONE);
                    isBlack = !isBlack;
                    g.fillOval(x, y, stoneWidth, stoneHeight);
                }
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(()->new GridByPainting());
        }
    }
    

    (Run it enter image description here

    CodePudding user response:

    It seems like you skipped over some of the important parts of the Oracle tutorial, Go Board

    My code has a logical model. My code has a drawing JPanel.

    The first thing I did was create a plain Java getter / setter class to hold a logical representation of a Go Board. I named this the Board class.

    The next thing I did was start my Swing GUI with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.

    I used the run method of my Runnable class to create the JFrame. The JFrame methods must be called in a specific order. This is the order I use for all my Swing applications.

    I separate the creation of the JFrame from the creation of any subsequent JPanels. I do this to keep my code organized, easy to read, and easy to understand.

    I extend a JPanel to create the drawing JPanel. I do this so I can override the paintComponent method of the JPanel class. The drawing JPanel draws (paints) the board state. That's all. Nothing else. Another class will take care of adding pieces to the logical Go board and repainting the drawing JPanel.

    The MoveListener class implements a MouseListener (extends a MouseAdapter) to respond to mouse clicks on the Go board. The MoveListener class keeps track of whose turn it is. In a more elaborate version of a Go board, you would have another plain Java getter / setter class to keep track of the game state.

    Here's the complete runnable code. I made all the classes inner classes so I could post this code as one block.

    import java.awt.BasicStroke;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class GoBoard implements Runnable {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new GoBoard());
        }
        
        private Board board;
        
        private DrawingPanel drawingPanel;
        
        public GoBoard() {
            this.board = new Board();
        }
    
        @Override
        public void run() {
            JFrame frame = new JFrame("Go Board");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            this.drawingPanel = new DrawingPanel(board);
            frame.add(drawingPanel, BorderLayout.CENTER);
            
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
        
        public class DrawingPanel extends JPanel {
    
            private static final long serialVersionUID = 1L;
            
            private final int margin, pieceRadius, lineSpacing;
            
            private Board board;
            
            public DrawingPanel(Board board) {
                this.board = board;
                
                this.margin = 60;
                this.pieceRadius = 40;
                this.lineSpacing = 100;
                this.setBackground(new Color(0x993300));
                int width = 8 * lineSpacing   margin   margin;
                this.setPreferredSize(new Dimension(width, width));
                this.addMouseListener(new MoveListener(board));
            }
            
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g;
                paintHorizontalLines(g2d);
                paintVerticalLines(g2d);
                paintPieces(g2d);
            }
            
            private void paintHorizontalLines(Graphics2D g2d) {
                int x = margin;
                int y1 = margin;
                int y2 = getHeight() - margin;
                
                g2d.setColor(Color.YELLOW);
                g2d.setStroke(new BasicStroke(3f));
                for (int index = 0; index < 9; index  ) {
                    g2d.drawLine(x, y1, x, y2);
                    x  = lineSpacing;
                }
            }
            
            private void paintVerticalLines(Graphics2D g2d) {
                int x1 = margin;
                int x2 = getWidth() - margin;
                int y = margin;
                
                g2d.setColor(Color.YELLOW);
                g2d.setStroke(new BasicStroke(3f));
                for (int index = 0; index < 9; index  ) {
                    g2d.drawLine(x1, y, x2, y);
                    y  = lineSpacing;
                }
            }
            
            private void paintPieces(Graphics2D g2d) {
                int[][] b = board.getBoard();
                for (int row = 0; row < b.length; row  ) {
                    for (int column = 0; column < b[row].length; column  ) {
                        int x = column * lineSpacing   margin;
                        int y = row * lineSpacing   margin;
                        if (b[row][column] == 1) {
                            g2d.setColor(Color.BLACK);
                            g2d.fillOval(x - pieceRadius, y - pieceRadius, 
                                    pieceRadius   pieceRadius, pieceRadius   pieceRadius);
                        } else if (b[row][column] == 2) {
                            g2d.setColor(Color.WHITE);
                            g2d.fillOval(x - pieceRadius, y - pieceRadius, 
                                    pieceRadius   pieceRadius, pieceRadius   pieceRadius);
                        }
                    }
                }
            }
            
        }
        
        public class MoveListener extends MouseAdapter {
            
            private boolean isBlackTurn = true;
            
            private Board board;
            
            public MoveListener(Board board) {
                this.board = board;
            }
    
            @Override
            public void mouseReleased(MouseEvent event) {
                Point point = event.getPoint();
                int margin = 60;
                int pieceRadius = 40;
                int lineSpacing = 100;
                int column = (point.x - margin   pieceRadius) / lineSpacing;
                int row = (point.y - margin   pieceRadius) / lineSpacing;
                int piece = (isBlackTurn) ? 1 : 2;
                board.setPiece(piece, row, column);
                drawingPanel.repaint();
                isBlackTurn = !isBlackTurn;
            }
            
        }
        
        public class Board {
            
            private int[][] board;
            
            public Board() {
                this.board = new int[9][9];
            }
            
            /**
             * <p>
             * This method inserts a piece on the board.
             * </p>
             * 
             * @param piece  - 1 for black, 2 for white
             * @param row    - row of piece
             * @param column - column of piece
             */
            public void setPiece(int piece, int row, int column) {
                this.board[row][column] = piece;
            }
    
            public int[][] getBoard() {
                return board;
            }
            
        }
    
    }
    
  • Related