我有一个 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/