WatchService冻结了JavaFX GUI

时间:2014-09-25 16:42:20

标签: java user-interface javafx freeze watchservice

我有一个JavaFX应用程序,必须在重命名文件时触发。我是WatchService的新手,我已经完成了演示并且它可以工作。

虽然,演示是1类的简单应用程序。现在我想在我自己的应用程序中实现它,创建一个单独的类来处理WatchService。

主要课程:

public class KochFractalDraw extends Application {
     @Override
        public void start(Stage primaryStage) throws IOException, InterruptedException {

                          //..define GUI etc..

            watchdirectory = new WatchDirectory();
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        watchdirectory.Register();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(JSF31KochFractalFX.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            });
    }

使用WatchDirectory:

public class WatchDirectory {

    WatchService watchService;
    Path path;
    WatchKey key;

    public WatchDirectory() throws IOException {

        this.watchService = FileSystems.getDefault().newWatchService();
        path = Paths.get("D:\\Test");
        path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);
    }

    public void Register() throws InterruptedException {
        for (;;) {

            this.key = watchService.take();
            for (WatchEvent<?> event : key.pollEvents()) {
                WatchEvent.Kind kind = event.kind();
                switch (kind.name()) {
                    case "ENTRY_CREATE":
                        System.out.println("Create triggered!");
                        break;
                    default:
                        System.out.println("Wrong event called.");
                        break;
                }

                boolean valid = key.reset();

                if (!valid) {
                    break;
                }
            }
        }
    }
}

我遇到的问题是它有效,但我的GUI立即冻结。因此我为什么要把watchdirectory.Register();在RunLater中,希望它不会影响主JavaFX应用程序线程。

(我知道它有效,因为每当我在“D:\ Test”中创建/重命名文件时,输出将继续响应“Create triggered!”)

2 个答案:

答案 0 :(得分:1)

感谢提示James_D

我让WatchDirectory成为Runnable。 在我的主要课程中,我用

运行它
new Thread(watchdirectory).start();

之前我接近这个解决方案,但后来我使用了.run(); ,再次冻结了GUI。没有意识到.start()之间的区别;和.run();

再也不会!

答案 1 :(得分:0)

Platform.runLater()旨在在某些时候让FX应用程序进程执行以运行其他运行的小程序并且存在并执行返回FX应用。

如果你在该过程中有无限循环,就像使用Watch Service一样,执行永远不会从它返回,自然FX应用程序冻结。

你绝对不能做到:

 while(true) {
    key = watchService.take();  
    ...
 }
使用Platform.runLater()时的

轮询循环。

相反,您必须将while(true)替换为某些FX组件,例如TimeLine,它每秒触发一次事件。忘记Runnable和Platform.runLater(),我认为要工作,你需要在FX内部进行轮询循环。

到目前为止,我还没有想出如何做到这一点。