0

I (A novice programmer) am trying to paint an oval over a JPanel. I am trying to use the method paint. However, it requires a Graphics argument. I get a NullPointerException when I include my Graphics as a argument because it is null, but I do not know how else to paint the oval. I tried repaint instead but nothing happened. Any help would be appreciated. Here is my main class:

public class Checkers extends JPanel{
 public static final int BOARDSQUARES = 8;
 public static final int BOARDSIZE = 75;
   private JPanel[][] board;
   private final Point point1;
   private final LineBorder border1;
   public JFrame frame;
   checkerPiece piece = new checkerPiece(this);
   Graphics g;

public Checkers(){
    board = new JPanel[BOARDSQUARES][BOARDSQUARES];
    point1 = new Point (BOARDSIZE,BOARDSIZE);
    border1=new LineBorder(Color.BLACK, 1);

}


/**
 * @param args the command line arguments
 */
public static void main(String[] args) {

     Checkers checkers = new Checkers();
   checkers.frame=checkers.createJFrame();

   checkers.board =checkers.createBoard(checkers.board, checkers.point1, checkers.border1);

  for (int y=0;y<BOARDSQUARES;y++){
      for (int x = 0;x<BOARDSQUARES;x++){
      checkers.frame.getContentPane().add(checkers.board[y][x]);

        }

  }

    checkers.paint(checkers.g);
}

private JPanel[][] createBoard (JPanel[][] board, Point point, LineBorder border1){
    for (int row = 0; row<BOARDSQUARES;row++){
        point.y=BOARDSIZE;
        for (int col = 0; col <BOARDSQUARES;col++){

            board[row][col] = new JPanel();
            board[row][col].setLocation(point);
            board[row][col].setVisible(true);
            board[row][col].setSize(BOARDSIZE,BOARDSIZE);
            board[row][col].setOpaque(true);
             if ((row%2==0&&col%2==0)||(row%2==1&&col%2==1)){
                board[row][col].setBackground(new Color (230,200,150));
            } else if ((row%2==0&&col%2==1)||(row%2==1&&col%2==0)) {

                 board[row][col].setBackground(new Color (165, 42,42) );
             }
             board[row][col].setBorder(border1);
                             point.y = point.y+BOARDSIZE;
        }
        point.x=point.x+BOARDSIZE;
    }

    return board;
}

private JFrame createJFrame (){
    JFrame mainFrame = new JFrame("Checkers");
    mainFrame.setSize(1000,1000);
    mainFrame.setVisible(true);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  mainFrame.add(new Checkers());
return mainFrame;
}
 @Override
public void paint (Graphics g){
    System.out.println("hi");
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g;

    piece.paint(g2d,board[0][0].getLocation().x,board[0][0].getLocation().y,Color.BLACK);

   }
}

A necessary snippet from my other class (cherkerPiece piece):

public void paint (Graphics2D g, int x, int y, Color color){
    g.setColor(color);
    g.fillOval(x, y, DIAMETER, DIAMETER);
}

Thank you for your help

rosseg
  • 38
  • 5
  • Are you seeing the message "hi" in the console? – ControlAltDel May 12 '15 at 15:59
  • You've covered your board with JPanels. Try not adding those and see if you can see your pieces – ControlAltDel May 12 '15 at 16:00
  • 2
    "Swing programs should override `paintComponent()` instead of overriding `paint()`."—[*Painting in AWT and Swing: The Paint Methods*](http://www.oracle.com/technetwork/java/painting-140037.html#callbacks). – trashgod May 12 '15 at 18:01
  • @ControlAltDel I get a bunch of errors relating to nullpointerexception as well as hi. – rosseg May 12 '15 at 18:49
  • @ControlAltDel Those jpanels make the checkerboard – rosseg May 12 '15 at 18:54
  • See also [Making a robust, resizable Swing Chess GUI](http://stackoverflow.com/q/21142686/418556). If this is a 'pieces on board' style game, I doubt it will need much custom painting. A collection of `JLabel` or `JButton` objects (either of which can display an icon) in a `GridLayout` will usually suffice. – Andrew Thompson May 13 '15 at 00:22

2 Answers2

0

To create something as complex as a checkers game, you should follow the model / view / controller pattern when creating your Java Swing GUI.

Checker Board GUI

I created a model class for a checker board square and another model class for a checker piece. I created a model class for the checker board and another model class to hold all of the checker pieces.

I created a view class to draw the checker board. I created another view class to create the main window.

I did not create any controller classes. This code just shows you how to draw a checker board. I put all of the classes together to make it easier to paste the code. You should separate the classes into separate Java files.

package com.ggl.testing;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class CheckerBoard implements Runnable {

    private Board board;

    private CheckerBoardPanel checkerBoardPanel;

    private JFrame frame;

    private Pieces pieces;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CheckerBoard());
    }

    public CheckerBoard() {
        this.board = new Board();
        this.pieces = new Pieces();
    }

    @Override
    public void run() {
        frame = new JFrame("Checker Board");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        checkerBoardPanel = new CheckerBoardPanel(board, pieces);
        frame.add(checkerBoardPanel);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public class CheckerBoardPanel extends JPanel {

        private static final long serialVersionUID = 3770663347384271771L;

        private Board board;

        private Pieces pieces;

        public CheckerBoardPanel(Board board, Pieces pieces) {
            this.board = board;
            this.pieces = pieces;
            this.setPreferredSize(board.getPreferredSize());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Square[][] checkerBoard = board.getBoard();

            for (int row = 0; row < checkerBoard.length; row++) {
                for (int column = 0; column < checkerBoard[row].length; column++) {
                    Square square = checkerBoard[row][column];
                    Rectangle drawingRectangle = square.getDrawingRectangle();
                    g.setColor(square.getColor());
                    g.fillRect(drawingRectangle.x, drawingRectangle.y,
                            drawingRectangle.width, drawingRectangle.height);
                }
            }

            List<Piece> checkerPieces = pieces.getPieces();

            for (Piece checkerPiece : checkerPieces) {
                Point coordinate = checkerPiece.getCoordinate();
                Rectangle drawingRectangle = checkerBoard[coordinate.x][coordinate.y]
                        .getDrawingRectangle();

                int x = drawingRectangle.x + drawingRectangle.width / 2;
                int y = drawingRectangle.y + drawingRectangle.height / 2;
                int radius = board.getSquareWidth() * 2 / 6;

                g.setColor(checkerPiece.getColor());
                g.fillOval(x - radius, y - radius, radius + radius, radius
                        + radius);
            }
        }
    }

    public class Board {

        private static final int BOARD_WIDTH = 8;
        private static final int SQUARE_WIDTH = 64;

        private Square[][] board;

        public Board() {
            this.board = initalizeBoard(BOARD_WIDTH, SQUARE_WIDTH);
        }

        private Square[][] initalizeBoard(int boardWidth, int squareWidth) {
            Square[][] board = new Square[boardWidth][boardWidth];

            int x = 0;
            int y = 0;

            for (int row = 0; row < boardWidth; row++) {
                for (int column = 0; column < boardWidth; column++) {
                    Square square = new Square();
                    if (isLightSquare(row, column)) {
                        square.setColor(Color.WHITE);
                    } else {
                        square.setColor(Color.LIGHT_GRAY);
                    }

                    square.setCoordinate(new Point(row, column));
                    square.setDrawingRectangle(new Rectangle(x, y, squareWidth,
                            squareWidth));

                    board[row][column] = square;

                    x += squareWidth;
                }
                x = 0;
                y += squareWidth;
            }

            return board;
        }

        public boolean isLightSquare(int row, int column) {
            if (row % 2 == 0) {
                if (column % 2 == 0) {
                    return true;
                } else {
                    return false;
                }
            } else {
                if (column % 2 == 0) {
                    return false;
                } else {
                    return true;
                }
            }
        }

        public Dimension getPreferredSize() {
            int width = SQUARE_WIDTH * 8 + 1;
            return new Dimension(width, width);
        }

        public Square[][] getBoard() {
            return board;
        }

        public int getSquareWidth() {
            return SQUARE_WIDTH;
        }

    }

    public class Square {

        private Color color;

        private Point coordinate;

        private Rectangle drawingRectangle;

        public Point getCoordinate() {
            return coordinate;
        }

        public void setCoordinate(Point coordinate) {
            this.coordinate = coordinate;
        }

        public Rectangle getDrawingRectangle() {
            return drawingRectangle;
        }

        public void setDrawingRectangle(Rectangle drawingRectangle) {
            this.drawingRectangle = drawingRectangle;
        }

        public Color getColor() {
            return color;
        }

        public void setColor(Color color) {
            this.color = color;
        }

    }

    public class Pieces {

        private List<Piece> pieces;

        public Pieces() {
            this.pieces = addPieces();
        }

        private List<Piece> addPieces() {
            List<Piece> pieces = new ArrayList<Piece>();

            Piece piece = new Piece();
            piece.setColor(Color.RED);
            piece.setCoordinate(new Point(2, 1));
            pieces.add(piece);

            piece = new Piece();
            piece.setColor(Color.BLACK);
            piece.setCoordinate(new Point(5, 0));
            pieces.add(piece);

            // Add the rest of the red and black pieces here

            return pieces;
        }

        public List<Piece> getPieces() {
            return pieces;
        }

        public void addPiece(Piece piece) {
            this.pieces.add(piece);
        }
    }

    public class Piece {

        private Color color;

        private Point coordinate;

        public Color getColor() {
            return color;
        }

        public void setColor(Color color) {
            this.color = color;
        }

        public Point getCoordinate() {
            return coordinate;
        }

        public void setCoordinate(Point coordinate) {
            this.coordinate = coordinate;
        }

    }

}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
  • Hi - thanks for the helpful answer. I have a few questions if you don't mind. – rosseg May 12 '15 at 23:54
  • 1. Why can you make an object of a class without giving the arguments like this : private Board board = new Board(); – rosseg May 12 '15 at 23:56
  • 2. What's the difference between using run and main? (I have 0 experience with the run method) – rosseg May 13 '15 at 00:53
  • 3. Where is paint component called? – rosseg May 13 '15 at 13:44
  • 1. It's my custom to set values in the constructor. This way, i can see at a glance which fields are static and which fields are instance variables. 2. The SwingUtilities invokeLater method expects a Runnable as a parameter. So, it's easier to make the JFrame class implement Runnable. All Swing applications should use the SwingUtilities invokeLater method to put the Swing components on the [Event Dispatch thread (EDT)](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html). 3. The paintComponent method is called whenever Swing requests a repaint. – Gilbert Le Blanc May 14 '15 at 15:15
  • I actually can't find where you used repaint. – rosseg May 19 '15 at 15:48
  • @Ross Grabs: The JPanel repaint happened when I called the pack method of JFrame. You would call a JPanel repaint in a controller class method when you've moved one of the checker pieces. – Gilbert Le Blanc May 19 '15 at 17:19
-1

you need to add a class that extends Canvas and do all your painting in that class. like this

public class FirstWindow extends JFrame
{
/**
 * 
 */
    private static final long serialVersionUID = 1L;

public FirstWindow()
{
    super("Kayte does not go to water parks");
    setSize(500, 500);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setResizable(false);
}
}

public class Start extends Canvas implements Runnable

public class Main
{

public static void main(String arg[])
{
    FirstWindow fw = new FirstWindow();

    Start game = new Start(500, 500);
    fw.add(game);
    fw.setVisible(true);
    new Thread(game).start();
}

}
  • Could you please explain what this class. Does FirstWindow represent my main class? What is serialvetsion? – rosseg May 12 '15 at 19:06
  • sure, The FristWindow class sets up a window. then I made a class called start which where all of my paint to that window is done. don't worry about the thread and the serialVersionUID. – ZergRushJoe May 14 '15 at 14:36
  • in start i have my run ,tick, and paint. I use a loop in run to call tick/update,game logic, and paint, paints whats happened. then in your class piece you add a paint and tick method to control each piece. – ZergRushJoe May 14 '15 at 15:00