简体   繁体   中英

Java usage of revalidate() and repaint() not properly working

So I tried creating a frame to perform a Diashow, but for some reason, I can see the only an empty frame and after everything is done, I see the last picture. What I wanted to see was each picture with a ~1 second pause in between. I used revalidate() / repaint() the way I suppose it is working, but Im fairly certain that the problem is there, since I cant think of another reason.

I am only starting to learn Java.Swing, so any input is really welcome to improve my skills. As I already said, I assume that the problem lies with my usage of revalidate(), but I cant fix it alone with google..

As input to the class I use an array of BufferedImage ,for which I want to create the diashow.

I also tried putting the images directly on my Container c instead of on the JPanel p , but it doenst work either way I intend it to work.

public class DiashowFrame extends JFrame {

Container c;
JPanel p;

public DiashowFrame(JFrame father,BufferedImage [] image) {
    c= getContentPane();
    c.setLayout(new FlowLayout());
    p = new JPanel();
    p.setLayout(new FlowLayout());
    p.setSize(500,500);
    c.add(p);

    setSize(500,500);
    setLocation(father.getX(),father.getY());
    setVisible(true);
    dia(p,image);

}

public static void dia(JPanel p,BufferedImage[] image) {

    JLabel def= new JLabel(new ImageIcon(image[0]));
    p.add(def);
    //c.repaint();
    p.revalidate();
    for(int x=1;x<image.length;x++) {

    try {

        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    //p.removeAll();
    //p.revalidate();
    Image imager = image[x].getScaledInstance(500, 500, 100);
    def = new JLabel(new ImageIcon(imager));
    p.add(def);
    p.revalidate();
    //p.repaint();

    }

}

}

Start by taking a look at Concurrency in Swing .

Swing, like most GUI frameworks, is single threaded AND not thread safe.

This means that any long running or blocking operation executed from within the Event Dispatching Thread will prevent the EDT from processing the Event Queue and update the UI in anyway.

While you could use a Thread to offload the wait time to a second thread, Swing is NOT thread safe, meaning you should never update/modify the UI directly or indirectly from outside the context of the EDT.

The simplest solution in your case is to simply use a Swing Timer . This allows you to specify a delay between updates (and if it's repeating or not), which is executed off the EDT, but when triggered, is notified within the context of the EDT, making easy and safe to use with Swing.

The Timer acts as a pseudo loop, each trigger of the Timer representing the next iteration

See How to use Swing Timers for more details

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM