My goal is to have the custom JComponent paint a rectangle at it's location and also paint an image if it has one. Right now, when I run the code it paints only the image at sprites/0.png, and also paints two black lines around the upper left hand corner. It doesn't paint any other rectangles or images. Below is my my custom JComponent class:
 public class GameSpace extends JComponent {
        private static final long serialVersionUID = 1L;
        private Image imageAtSpace = null;
        public static final int DEFAULT_WIDTH = 100;
        public static final int DEFAULT_HEIGHT = 100;
        public GameSpace() {
            setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        }
        public GameSpace(int x, int y) {
            this();
            setLocation(x, y);
            setVisible(true);
        }
        /*
      Other constructors removed for brevity
      */
        public void setImage(Image image) {
            this.imageAtSpace = image;
        }
        public void removeImage() {
            this.imageAtSpace = null;
        }
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.BLACK);
            g.drawRect(getX(), getY(), getWidth(), getHeight());
            if (!isEmpty())
                g.drawImage(imageAtSpace, getX(), getY(), this);
        }
        public boolean isEmpty() {
            return imageAtSpace == null;
        }
    }
And here is the class that creates the panel and JFrame:
public class GameView {
    JPanel mainGamePanel;
    private static final int DEFAULT_NUM_SPOTS = 16;
    private static final int SPOTS_PER_ROW = 4;
    private static final int SPOTS_PER_COLUMN = 4;
    private static final int DEFAULT_WIDTH = GameSpace.DEFAULT_WIDTH;
    private static final int DEFAULT_HEIGHT = GameSpace.DEFAULT_HEIGHT;
    Map<Integer, GameSpace> gameSpaces = new HashMap<Integer, GameSpace>();
    public GameView() {
        mainGamePanel = defaultLoad();
    }
    private JPanel defaultLoad() {
        JPanel panel = new JPanel();
        panel.setLayout(null);
        panel.setFocusable(true);
        panel.setSize(400, 400);
        int startX =0;
        int startY = 0; 
        for (int i = 0; i < DEFAULT_NUM_SPOTS; i++) {
            int xLocation = startX + (i % SPOTS_PER_ROW)*DEFAULT_WIDTH;
            int yLocation = startY + (i / SPOTS_PER_COLUMN)*DEFAULT_HEIGHT;
            GameSpace gs = new GameSpace(xLocation, yLocation);
            gs.setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
            gs.setImage(new ImageIcon(this.getClass().getResource("/sprites/" + i + ".png")).getImage());
            gameSpaces.put(i, gs);
            panel.add(gs);
            panel.revalidate();
            panel.repaint();
        }
        panel.setVisible(true);
        return panel;
    }
    public static void main(String...args) {
        JFrame frame = new JFrame("test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new GameView().mainGamePanel);
        frame.setSize(400, 400);
        frame.revalidate();
        frame.repaint();
        frame.setVisible(true);
    }
}
I'm still a bit unsure of when I need to revalidate/repaint, so I kind of just threw it everywhere in an attempt to solve the problem, apologies if there's any redundancy. Any help for why it's not painting a grid of rectangles with images inside of them would be appreciated. Even if I comment out adding the image, it won't paint rectangles.
