Search code examples
javaswingjpaneljscrollpanerepaint

My Swing GUI does not update. Why?


enter image description here

So, I am making a GUI in which the user has the ability to add or remove panels. To simulate that, I made a TimerTask which takes the name of the target JPanel and the parent which contains the JPanel.
It counts down to 0 and after that it removes the JPanel from the parent and calls repaint() on the parent and grandparent.

Although the old panel gets removed, the other components contained in the parent do not come up to take its place. It can be seen in the picture that the scroll bar still indicated 2 components.

I have to manually drag the scroll bar down to see it change and that is when the component below comes up to take its place.

Why is this happening?

Here is how the components are nested:

JScrollPane (grandparent)
|
|-> JPanel (parent)
    |
    |-> JPanel (target)  

SSCCE is not possible because the JPanels are populated with data from XML file and uses JAXB so .. it is not possible :( but here is a snippet from the TimerTask

import java.util.TimerTask;
import javax.swing.*;

public class RemoverTask extends TimerTask{
    StudentPanel s;
    JPanel h;
    JScrollPane p;
    public RemoverTask(StudentPanel s,JPanel holder,JScrollPane pane){
        this.s = s;
        h = holder;
        p = pane;
    }

    @Override
    public void run(){
        long x = Integer.MAX_VALUE/2;
        JFrame frame = new JFrame("Counter");
        JTextArea area = new JTextArea();
        JScrollPane pane = new JScrollPane(area);
        pane.setPreferredSize(new java.awt.Dimension(350, 350));
        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
        while(x > 100){
            x =  x - 1500;
            area.append("Value of X: " + x + "\n");
        }
        if(!frame.isVisible()){
            frame.dispose();
        }
        h.remove(s);
        h.repaint();
        pane.repaint();
    }
}

Solution

  • You can still make an sscce, just don't worry about the xml data etc. Simplify the problem, man. Also, don't use a java.util.Timer with a Swing app but rather a javax.swing.Timer, a Swing Timer. Else you will be making Swing changes off of the Swing EDT which is dangerous.

    A problem: you never call revalidate() on the container. You would usually call revalidate() before calling repaint() on the container when making changes to it. The revalidate tells the layout managers to layout their components which is necessary to change the GUI.