显示文本文件中包含的路径的图像

时间:2014-01-06 22:06:12

标签: java swing awt javabeans bufferedreader

我正在尝试使用JFrame显示图像,但该图像的路径每两秒更改一次。该路径包含在文本文件中。我可以毫无问题地在JFrame中显示单个图像,并且可以使用计数器显示一系列不同的图像,前提是我对路径进行硬编码。但我只是不知道如何每隔2秒显示一个在文本文件中记录新路径的图像。

我尝试使用缓冲区读取器读取文本文件然后将路径保存到bean但是因为我在循环中有缓冲区读取器,所以如果我从循环外部调用它,则返回null。

除了这种接缝之外,还有很长时间才能完成这项任务。有人能提出一个简单的方法来实现我的目标。我不能缝合从树上看木头。

感谢。

顺便说一句:这不是一个家庭作业,它只是我正在制作的个人计划。

2 个答案:

答案 0 :(得分:2)

以下解决方案最适合未运行Java 7+的用户。考虑查看MadProgrammer的解决方案,这对几乎每个应用程序来说都会更好。

可能不是最好的答案,只是觉得至少在这里找到一个问题会很好。

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * @author Obicere
 */
public class LoadImageTest {

    public LoadImageTest() {
        final JFrame frame = new JFrame("Load Image Test");
        final MyPanel panel = new MyPanel(ImageScanner.loadImage());
        final ImageScanner scanner = new ImageScanner(panel);

        frame.add(panel);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        new Thread(scanner).start();
    }

    public static void main(final String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new LoadImageTest();
            }
        });
    }

    public static class ImageScanner implements Runnable {

        private static final File PATH_FILE = new File("image.txt");
        private final MyPanel instance;
        private long lastModified = PATH_FILE.lastModified();

        public ImageScanner(final MyPanel panel) {
            this.instance = panel;
        }

        @Override
        public void run() {
            while (true) {
                if (PATH_FILE.lastModified() != lastModified) {
                    System.out.println("Loading");
                    instance.setImage(loadImage());
                    lastModified = PATH_FILE.lastModified();
                }
                try {
                    Thread.sleep(50);
                } catch (final Exception ignored) {

                }
            }
        }

        public static Image loadImage() {
            try {
                final byte[] data = Files.readAllBytes(Paths.get(PATH_FILE.toURI()));
                final String path = new String(data);
                System.out.println(path);
                return ImageIO.read(new URL(path));
            } catch (final Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    public class MyPanel extends JPanel {

        private Image render;

        public MyPanel(final Image render) {
            this.render = render;
        }

        @Override
        public void paintComponent(final Graphics g) {
            super.paintComponent(g);
            g.drawImage(render, 0, 0, this);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(render.getWidth(this), render.getHeight(this));
        }

        public void setImage(final Image image) {
            this.render = image;
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    repaint();
                    revalidate();
                }
            });
        }

    }
}

这样做会创建一个新线程来检查文件是否已更新。该线程将运行EDT,因此无需担心冻结应用程序。我还添加了一个50毫秒的超时,以免过多地对CPU征税。这取决于您自行决定。

这将是加载图像并将其渲染到JPanel上。这只是关于如何做到这一点的简单草案,仅仅是一个概念,而不是你真正想要使用的代码。我甚至觉得写这个有点不好。

答案 1 :(得分:2)

如果您使用的是Java 7,那么您可以利用内置的文件监视器服务...

首先看看Watching a Directory for ChangesConcurrency in Swing,特别是Worker Threads and SwingWorker

SwingWorker将允许您监视事件调度线程之外的更改,允许您的UI继续响应用户和系统事件。

SwingWorker还具有将更新重新同步回EDT的便捷方法,允许您安全地更新UI。

public class WatcherWorker extends SwingWorker<Void, String> {

    private WatchService watcher;
    private Map<WatchKey, Path> keys;
    private Path path;

    public WatcherWorker(Path path) throws IOException {
        watcher = FileSystems.getDefault().newWatchService();
        this.path = path;
        path.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_CREATE);
    }

    @Override
    protected Void doInBackground() throws Exception {
        while (true) {

            WatchKey key = watcher.take();
            List<String> lines = Files.readAllLines(path, Charset.defaultCharset());
            if (lines.size() > 0) {
                String imagePath = lines.get(0);
                publish(imagePath);
            }

        }
    }

    @Override
    protected void process(List<String> chunks) {
        String imagePath = chunks.get(chunks.size() - 1);
        // load new image
        // apply image to what ever you need to use it with
        // This would assume that you have a reference to something capable of
        // using the said image ;)
    }

}

然后你可以使用类似......

的东西
Path p1 = Paths.get("/path/to/configuration/config.txt");
WatcherWorker worker = new WatcherWorker(p1);
worker.execute();