【问题标题】:Refreshing JPanel after loading next Image into it将下一个图像加载到其中后刷新 JPanel
【发布时间】:2013-08-20 07:00:40
【问题描述】:

我创建了ImagePanel,它能够显示指定目录中的图像 -> 它休眠 1 秒并从 java 项目的目录中加载下一个图像。 它实际上加载了下一个图像,但不显示(它不刷新面板),当它完成目录中的所有文件时,它只显示目录中的最后一个图像。我想让它在加载每张图片后刷新。

  import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

public class Okno extends JFrame {
    JPanel jp;
    ImagePanel ImagePanel;
    JButton buttonExit;
    JButton buttonWyjscie;

    public Okno() {

    }

    public void createGUI() {
        setSize(400, 400);
        setLayout(new GridLayout());
        buttonExit = new JButton("Exit");
        buttonWyjscie = new JButton("Wyjscie");
        // Sluchacz sluchacz = new Sluchacz();

        // buttonExit.addActionListener(sluchacz);
        buttonExit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);

            }
        });

        jp = new JPanel();
        jp.setBorder(new LineBorder(new Color(40, 120, 80), 4));

        ImagePanel = new ImagePanel();
        ImagePanel.setBorder(new LineBorder(Color.blue, 4));
        jp.add(buttonExit);
        add(jp);
        add(ImagePanel);

        setVisible(true);
        slajd();
        setDefaultCloseOperation(EXIT_ON_CLOSE);

    }

    public void slajd() {
        try {
            File f = new File(".");
            File[] tablicaPlikow = f.listFiles();
            for (File el : tablicaPlikow) {

                String rozszerzenie = el.getName().substring(
                        el.getName().length() - 3);

                if (rozszerzenie.equals("jpg") || rozszerzenie.equals("peg")) {
                    System.out.println(rozszerzenie);
                    ImagePanel.setImage(el);
                }
                repaint();
            }
            setVisible(true);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Okno().createGUI();
            }
        });

    }

}

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class ImagePanel extends JPanel {
    private BufferedImage image;

    public ImagePanel() {
    }

    public ImagePanel(String sciezka) {
        setImage(new File(sciezka));
    }

    public void setImage(File plik) {
        try {
            image = ImageIO.read(plik);
            System.out.println("tutaj");
            repaint();
            Thread.sleep(1000);
        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    public void paint(Graphics g) {
        if (image != null) {
            Image b = image.getScaledInstance(getWidth(), getHeight(),
                    Image.SCALE_FAST);
            g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
        }

    }

}

【问题讨论】:

  • 你有什么尝试?为什么他们没有工作?他们以何种方式没有完成您期望他们做的事情?是否有任何错误消息、异常或不良行为?

标签: java image swing slideshow thread-sleep


【解决方案1】:

简短的回答可能是:在方法slajd中,调用repaint();后,添加

Thread.sleep(1000);

然而,这与 Swing 基于事件的性质完全相反,在这种特殊情况下甚至不起作用,因为出于效率原因,Swing 不会立即执行 repaint() 调用。在所有事件处理结束后,它只“收集”并执行一次。如果您在事件处理程序(直接或间接)中包含睡眠期(或任何其他长时间运行的操作),则重新绘制将被延迟,并且应用程序对这一点非常没有响应,就像在这种情况下,不是真正的工作。

您需要做的是在 createGUI 中实例化一个 Swing Timer(javax.swing.Timer;不要将它与 java.util.Timer 或其他一些包中的 Timer 类混淆),它每 1 秒触发一次,而不是调用slajd()。第一次触发应该是立即的,或者您可以包含显示第一个文件的代码。将替换slajd() 的关联侦听器应跟踪要显示的下一个文件。您很可能希望将此侦听器设置为具有支持此跟踪的字段、指向 ImagePanel 显示文件的位置的指针等的成熟类。

欲了解更多信息,请阅读Java's Tutorial on How to Use Swing Timers

【讨论】:

  • 1) 因为如果问题就是问题,它会起作用(我可能会使用它)。 2)因为我家里停电太多,想保存我的回复。在那之后我也做了一些其他的部分保存,而且 3)因为我的答案(如果需要,请检查它们)通常很长并且(希望)完整,而有些提问者只想快速回复。
  • 并非如此。为了与我上面的第 3) 点保持一致,我将解释为什么 Thread.sleep 不起作用。非常感谢您帮助我们做出更好的回答。
【解决方案2】:

睡在EDT 中会阻止秋千进行绘画,因此您只能看到最后一张图片。不用在事件派发线程中休眠,而是使用 swing Timer 来执行重复任务:

private final ActionListener timerTask = new ActionListener() {
    @Override
    public void actionPerformed(final ActionEvent e) {
        // Whatever you need to to that
        showNextImage();
    }
};

Timer timer = new Timer(1000, timerTask);
timer.start();

如果加载图片需要很长时间,请考虑使用background task 将下一张图片预加载到内存中,而不会阻塞 EDT。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 2019-12-07
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多