logging - 转换为 UI 的记录器条目停止随时间更新

标签 logging javafx javafx-2

我有一个 javafx.concurrent.Task 在后台运行一些代码并使用 java.util.logging.Logger 提供有关其状态的信息。我需要在主线程的 UI 中显示此日志条目。我该怎么做?

这是我为了解决上下文问题而做的一个简单的玩具项目

@Override
public void start(Stage primaryStage) {


    ListView<String> list = new ListView<>();
    final ObservableList<String> items =FXCollections.observableArrayList ();
    list.setItems(items);

    Task<String> task = new Task<String>() {

        @Override
        protected String call() throws Exception {
            doStuff();
            return "yey";
        }
    };

    new Thread(task).start();



    Scene scene = new Scene(list, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}

private void doStuff() {
    for (int i=0;i<10;i++) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger("LoggerUI").log(Level.INFO, "error");
        }
        Logger.getLogger("LoggerUI").log(Level.SEVERE, "whatever");
    }

[...]
}

我试过了,但是不行

public class LoggerUI extends Application {

@Override
public void start(Stage primaryStage) {
    System.out.println("UI"+ Thread.currentThread().getId());


    ListView<String> list = new ListView<>();
    final ObservableList<String> items =FXCollections.observableArrayList ();
    list.setItems(items);

    Logger.getLogger("LoggerUI").addHandler(new Handler() {

        @Override
        public void publish(LogRecord lr) {
            System.out.println("publish()"+ Thread.currentThread().getId());

            items.add(lr.getMessage());
        }

        @Override
        public void flush() {
            System.out.println("flush");
        }

        @Override
        public void close() throws SecurityException {
            System.out.println("close");

        }
    });

    Task<String> task = new Task<String>() {

        @Override
        protected String call() throws Exception {
            doStuff();
            return "yey";
        }
    };

    new Thread(task).start();



    Scene scene = new Scene(list, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}

private void doStuff() {

    System.out.println("doStuff()"+ Thread.currentThread().getId());
    for (int i=0;i<300;i++) {
        final int j =i;
        try {
            Thread.sleep(30);
        } catch (InterruptedException ex) {

            Logger.getLogger("LoggerUI").log(Level.INFO, "error");
        }

        Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    System.out.println("runLater()"+ Thread.currentThread().getId());
                    Logger.getLogger("LoggerUI").log(Level.SEVERE, "whatever" +j);
                }
            });
    }

   [..]

}
}

它显示前 20-30 个条目,然后停止更新 UI

最佳答案

更新:这实际上不是 JavaFX 问题,而是 Java 日志记录问题。

将 Logger 存储到变量中,因为 Logger.getLogger() 返回的 Logger 每次都不相同,它们被缓存、垃圾收集和填充。

private Logger logger = Logger.getLogger("LoggerUI");

并按如下方式使用:

logger.addHandler(new Handler() { ... });

logger.log(Level.SEVERE, "whatever" +j);

此外,我建议将 Platform.runLater() 调用移动到 publish() 方法,这样您的记录器就可以在任何线程中工作。

关于logging - 转换为 UI 的记录器条目停止随时间更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12339853/

相关文章:

java - 为什么 log4j 记录到两个单独的文件?

java - 使用 Springboot org.apache.commons.logging 禁用 PDFBox 日志记录

JavaFX 错误 : ANOMALY: meaningless REX prefix used

java - (JavaFX) 如何使用基本 java 类更改 fxml 文件中编码的 ImageView 中的图片?

java - 自动视频快照

swing - 用于纯 Windows 桌面应用程序的 JavaFX 2 与 Swing

c++ - QMessageLogger 魔法是如何工作的?

java - 在JavaFX中,有没有办法先显示选项卡名称,然后显示图形?

javafx-2 - JavaFx 2 - 自包含应用程序及其偏好、数据库等

ruby-on-rails - Ruby On Rails 4.2 的可视化日志查看器