Custom JComponent Not Being Added to JPanel

I'm having a bit of a stickler with what I thought was quite a simple problem.

I have a custom JComponent Ball that is nothing more than a simple oval. I'm trying to add the ball to a JPanel which I have set as the JFrame's default content pane (via frame.setContentPane(mainPanel)). Along with the ball, I have two other components of class Paddle, another custom JComponent I have created. Oddly, the paddles can be added just fine.

The panel in question uses, on purpose, absolute layout to position the elements, since this was supposed to be a simple recreation of the Pong game.

I ran a simple test after adding the ball and both paddles to the JPanel, and found that the array of Components returned only listed two: the paddles. The full code adding all of them and initializing the JPanel and JFrame is as follows:

public Pong()
{
    frame = new JFrame("Pong");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    mainPanel = new JPanel(null);

    mainPanel.setBackground(Color.black);
    mainPanel.setPreferredSize(new Dimension(500, 500));

    player = new Paddle(20, 100);
    enemy = new Paddle(20, 100);
    ball = new Ball(5, Color.GREEN);

    mainPanel.add(player);
    mainPanel.add(enemy);
    mainPanel.add(ball);
    enemy.setColor(Color.RED);

    frame.setContentPane(mainPanel);
    frame.pack();

    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    int x = screen.width/2 - frame.getWidth()/2;
    int y = screen.height/2 - frame.getHeight()/2;
    frame.setLocation(x, y);

    mainPanel.addKeyListener(mc);

    frame.setVisible(true);

    mainPanel.repaint();

    x = mainPanel.getWidth()/2 - ball.getWidth()/2;
    y = mainPanel.getHeight()/2 - ball.getHeight()/2;
    System.out.println("X: " + x + ", Y: " + y);
    ball.setLocation(x, y);

    x = 0;
    y = mainPanel.getHeight()/2 - player.getHeight()/2;
    System.out.println("X: " + x + ", Y: " + y);
    player.setLocation(x, y);

    x = mainPanel.getWidth() - enemy.getWidth();
    y = mainPanel.getHeight()/2 - enemy.getHeight()/2;
    System.out.println("X: " + x + ", Y: " + y);
    enemy.setLocation(x, y);

    System.out.println(Arrays.deepToString(mainPanel.getComponents()));

    mainPanel.repaint();

    frame.addMouseListener(new MouseAdapter()
    {
        @Override
        public void mousePressed(MouseEvent e)
        {
            mainPanel.requestFocus();
        }
    });

    dm.start();
    mainPanel.requestFocus();
}

The code for the ball is as follows [Note: The ball is private because it is an inner class of class Pong, which does not extend anything]:

private class Ball extends JComponent
{
    private int radius;
    private Color color;

    public Ball(int size, Color c)
    {
        if(size > 0)
            radius = size;
        else
            radius = 1;
        this.setPreferredSize(new Dimension(radius, radius));
        color = c;
    }

    public Ball(int size)
    {
        this(size, Color.RED);
    }

    //Getters and Setters...

    @Override
    public void paintComponent(Graphics g)
    {
        System.out.println("Radius: " + radius);
        g.setColor(color);
        g.fillOval(0, 0, radius, radius);
    }
}

This isn't the first time I've encountered this problem when working on projects, and it always seems to occur when I'm using custom JComponents along with absolute positioning on a JPanel, although in still other projects, I don't seem to have a problem with this. It's probably something very simple that I'm overlooking, but I can't think of what it is, for the life of me. Any answers to this would be greatly appreciated.

If absolutely necessary, all the lines of code for this project can be found here (Just over 300 lines total).

Thanks in advance for any help!

Answers


When you add components to a panel using a null layout then you are responsible for setting the size and location of the component.

If you don't set the size then it will be zero and so there is nothing to paint.


The solution is silly and simple.

Add the following call the constructor and setRadius method in your Ball class:

this.setSize(new Dimension(radius, radius));

And all should be well. Basically, preferred size isn't enforced, so be explicit: set the size. Otherwise, when repainting the JPanel, this component has size of 0 and is skipped.

(Edited based on comment, thanks, my Swing is rusty)


Need Your Help

HTML, CSS: text align with display: inline not working

html css

I'm trying to build a website. Text-align: center does not work with display: inline-block but is there any way to my text-align to work with display: inline-block?