javaswingjpanelpaintrepaint

repaint() not updating panel?


I have a class (not public, so you probably do not know the class) which is drawing a picture with picture.draw(g2). With picture.changeToDry() I can change the picture. It works fine, when I call the picture and change it in implemented paintComponent() method. But when I call changeToDry() and after it repaint(), it does not work. It just shows the default picture but does not update it. What do I have to do, so that I can change the picture and update the JPanel in another method? It has to be something with the repaint() because the methods work in paintComponent() but not elsewhere.

EDIT: update() will be called in another class. Plus, as I mentioned in the comments, I cannot give more information for the class, as it is a private, teaching-only class. And obviously it should work. Otherwise my teacher would not give it to us. EDIT 2: I have another class ClimateFrame which is drawing a frame. There I am calling update()

public class ClimatePanel extends JPanel {
    ClimatePicture picture = new ClimatePicture(100, 100);
    
    public void update() {
        picture.changeToDry();
        repaint(); // does not work
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        // picture.changeToDry() would work here
        picture.draw(g2);   
    }
}




public class ClimateFrame extends JFrame {
    
    public ClimateFrame() {
        setTitle("A task");
        setLayout(new BorderLayout());
        add(new ClimatePanel(), BorderLayout.CENTER);
    }
    
    public static void main(String [] args) {
        
        ClimateFrame frame = new ClimateFrame ();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setVisible(true);
        ClimatePanel climatePanel = new ClimatePanel();
        climatePanel.update();
        
        
    }
}


Solution

  • There is your problem:

    public class ClimateFrame extends JFrame {
        
        public ClimateFrame() {
            setTitle("A task");
            setLayout(new BorderLayout());
            add(new ClimatePanel(), BorderLayout.CENTER);
        }
        
        public static void main(String [] args) {        
            ClimateFrame frame = new ClimateFrame ();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(800, 600);
            frame.setVisible(true);
            ClimatePanel climatePanel = new ClimatePanel(); // ****** here ****
            climatePanel.update();
        }
    }
    

    You're creating a new ClimatePanel instance at the indicated line and changing its state rather than the state of the separate originally created and displayed one. This aligns with one of my guesses made in comments above:

    Right now we can guess:

    • it could be a Swing threading issue,
    • or you could be updating the wrong instance (THIS ONE)

    The solution: don't create a new ClimatePanel instance but instead create a ClimatePanel field, give it a single ClimatePanel reference, add it to the GUI, and later update its state, now the state of the displayed instance.

    e.g.,

    public class ClimateFrame extends JFrame {
        private ClimatePanel climatePanel = new ClimatePanel(); // ADD
        
        public ClimateFrame() {
            setTitle("A task");
            setLayout(new BorderLayout());
            // add(new ClimatePanel(), BorderLayout.CENTER); // REMOVE
            add(climatePanel, BorderLayout.CENTER); // ADD    
        }
        
        // allow visibility of the climate panel method
        public void updateClimatePanel() {
            climatePanel.update();
        }
        
        public static void main(String [] args) {        
            ClimateFrame frame = new ClimateFrame ();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(800, 600);
            frame.setVisible(true);
            // ClimatePanel climatePanel = new ClimatePanel(); // REMOVE
            frame.updateClimatePanel();
        }
    }