Why is paintComponent(Graphics) not being called despite the fact I am declaring a layout manager

I am subclassing both JFrame and JPanel objects to build a simple menu UI for a game. The menu is a PNG image that will be rendered inside the JPanel’s paintComponent(Graphics) method. I hooked a KeyListener to the JFrame in order to receive keyboard commands, and it is working (space bar exits the program). Although I am declaring a layout manager (BorderLayout), as advised by other Stack Overflow posts, JPanel’s paintComponent() is not called.

My code follows below:

public class MainScreen extends JFrame {

    public MainScreen() {
        super();
        initialize();
    }

    public final void initialize() {
        setLayout(new BorderLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(new Menu(this), BorderLayout.CENTER);
        setResizable(false);
        setLocationRelativeTo(null);
    }

    class Menu extends JPanel implements KeyListener {
        JFrame frame;
        Image imagem;

        public Menu(JFrame frame) {
            super();
            this.frame = frame;            
            initialize();
        }

        public final void initialize() {
            frame.removeAll();
            frame.setTitle("Menu principal");
            frame.setSize(new Dimension(Comuns.LARGURA, Comuns.ALTURA));
            frame.addKeyListener(this);

            ImageIcon icone = new ImageIcon("res\MenuScreen.png");
            imagem = icone.getImage();

            frame.setVisible(true);
        }

        @Override
        public void keyTyped(KeyEvent e) {
            // nada aqui
        }

        @Override
        public void keyPressed(KeyEvent e) {
            int c = e.getKeyCode();
            switch (c) {
                case KeyEvent.VK_1:
                    frame.removeKeyListener(this);
                    new Fase_1(frame);
                    break;

                ...

                case KeyEvent.VK_SPACE:
                    frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
                    break;
                default:
                    break;
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            // nada aqui
        }

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

            Graphics2D gd = (Graphics2D) g;
            if (imagem != null) {
                gd.drawImage(imagem, 0, 0, frame);
            }
        }       

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(Comuns.LARGURA, Comuns.ALTURA);
        }
    }
}

Answer

This question was answered in the comments by @STaefi so I’m making this answer a CW

In the public final void initialize() of Menu class, remove the frame.removeAll(); and there you go.

A good practice is to call the JFrame#setVisible after all the initialization, not int the initialization a child component.

Leave a Reply

Your email address will not be published. Required fields are marked *