revalidate()和repaint()的Java使用不正常工作

时间:2018-01-14 19:00:31

标签: java swing

所以我尝试创建一个框架来执行Diashow,但由于某种原因,我可以看到唯一一个空框架,一切都完成后,我看到了最后一张图片。我想看到的是每张图片之间暂停约1秒钟。我使用revalidate()/ repaint()的方式我认为它正在工作,但我相当确定问题存在,因为我无法想到另一个原因。

我只是开始学习Java.Swing,所以我们非常欢迎任何输入来提高我的技能。正如我已经说过的,我认为问题在于我使用了revalidate(),但是我不能单独用google修复它。

作为类的输入,我使用 BufferedImage 数组,我想为其创建diashow。

我还尝试将图片直接放在我的容器c 上,而不是放在 JPanel p 上,但无论我打算如何工作,它都能正常工作。

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();

    }

}

}

1 个答案:

答案 0 :(得分:1)

首先看一下Concurrency in Swing

与大多数GUI框架一样,Swing是单线程的,而不是线程安全的。

这意味着从事件调度线程中执行的任何长时间运行或阻塞操作都将阻止EDT处理事件队列并以任何方式更新UI。

虽然您可以使用Thread将等待时间卸载到第二个线程,但Swing不是线程安全的,这意味着您永远不应直接或间接地从EDT上下文之外更新/修改UI。 / p>

在您的情况下,最简单的解决方案是简单地使用Swing Timer。这允许您指定更新之间的延迟(如果它重复或不重复),这是在EDT之外执行的,但是当被触发时,在EDT的上下文中被通知,使得使用Swing变得容易和安全。

Timer充当伪循环,Timer的每个触发器代表下一次迭代

有关详细信息,请参阅How to use Swing Timers