1

我有一个 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”中创建/重命名文件时,输出都会继续响应“创建触发!”)

4

2 回答 2

1

感谢您的提示 James_D

我已将 WatchDirectory 设为 Runnable。在我的主要课程中,我使用它来运行它

new Thread(watchdirectory).start();

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

再也不!

于 2014-09-25T17:02:44.247 回答
0

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

如果您在该进程中有无限循环,例如如何使用 Watch Service,则执行永远不会从它返回,FX 应用程序自然会冻结。

你绝对不能这样做:

 while(true) {
    key = watchService.take();  
    ...
 }

使用 Platform.runLater() 时的轮询循环。

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

到目前为止,我还没有弄清楚如何做到这一点。

于 2015-11-24T15:55:40.377 回答