Search code examples
javaswingjpanelawtsetbackground

Why setBackground works only the first time? (JPanel)


In an outer class I call these methods many times, but setBackground() works only the first time I call any of these methods.

For example, I have objects CellPane cellpane1, cellpane2 and when I call cellpane1.drawPlayer() for the first time it works as expected and when I call cellpane2.drawWall() for the first time it works as expected too. But when I call drawWall() for cellpane1, cellpane1.drawWall() after I called cellpane1.drawPlayer(), it doesn't work. The background color is not changing.

Do I need to repaint or reinvalidate, or what ? I'm new to these stuff. :( What I'm doing wrong?

private static class CellPane extends JPanel {

    private Color defaultBackground;

    private CellPane() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                defaultBackground = getBackground();
                setBackground(Color.BLUE);
            }

            @Override
            public void mouseExited(MouseEvent e) {
                setBackground(defaultBackground);
            }
        });
    }

    private void drawDefault() {
        setBackground(defaultBackground);
    }

    private void drawBoxOnGoal() {
        defaultBackground = getBackground();
        setBackground(Color.decode("#4a3d32"));
    }

    private void drawPlayerOnGoal() {
        defaultBackground = getBackground();
        setBackground(Color.decode("#f9cda8"));
    }

    private void drawGoal() {
        defaultBackground = getBackground();
        setBackground(Color.decode("#f9cda8"));
    }

    private void drawBox() {
        defaultBackground = getBackground();
        setBackground(Color.decode("#7a5230"));
    }

    private void drawPlayer() {
        defaultBackground = getBackground();
        setBackground(Color.YELLOW);

    }

    private void drawWall() {
        defaultBackground = getBackground();
        setBackground(Color.RED);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(50, 50);
    }

}

[EDIT]

Example:

public class MainClass {



public static void main(String[] args) {
    new MainClass();
}

private MainClass() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { }

            JFrame frame = new JFrame("Test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new BorderLayout());

            frame.add(new Map());

            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}

private static class Map  extends JPanel implements ActionListener{

    CellPane cellPane;
    boolean flag = true;

    JButton button = new JButton("button");

    public Map() {
        setLayout(new GridBagLayout());

        button.addActionListener(this);

        add(button);

        create(flag);
    }

    public void create(boolean flag) {
        GridBagConstraints gbc = new GridBagConstraints();

        cellPane = new CellPane();
        gbc.gridx = 0;
        gbc.gridy = 0;
        if(flag)
            cellPane.drawPlayer();
        else cellPane.drawWall();
        add(cellPane, gbc);
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        flag = false;
        create(flag);
    }

}


@SuppressWarnings("serial")
private static class CellPane extends JPanel {

    private Color defaultBackground;


    private void drawPlayer() {
        defaultBackground = getBackground();
        setBackground(Color.YELLOW);

    }

    private void drawWall() {
        defaultBackground = getBackground();
        setBackground(Color.RED);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(50, 50);
    }

}}

I know that it's not the perfect example, but it's runnable. So I want to change the background of the cellPane when I click the button. The constructor calls create(flag) when flag is true and the background is set to YELLOW. Then I click the button, the flag changes to false and call create(flag) where flag=false, so it calls the cellPane.setWall() instead which sets the background RED, but it doesn't.

What I'm doing wrong? Maybe something easy, but I'm new to these stuff.


Solution

  • You're not changing the color of the cellPane when clicking the button. You're creating another cellPane with a different color, and you're adding it in the same gridbag cell as the existing one.

    Just change the color, and it will work fine:

        public Map() {
            setLayout(new GridBagLayout());
    
            button.addActionListener(this);
    
            add(button);
    
            create();
            draw();
        }
    
        private void draw() {
            if (flag) {
                cellPane.drawPlayer();
            }
            else {
                cellPane.drawWall();
            }
        }
    
        private void create() {
            GridBagConstraints gbc = new GridBagConstraints();
    
            cellPane = new CellPane();
            gbc.gridx = 0;
            gbc.gridy = 0;
            add(cellPane, gbc);
        }
    
        @Override
        public void actionPerformed(ActionEvent arg0) {
            flag = false;
            draw();
        }