执行进程时更新 TextArea
Update TextArea while executing processes
我发现当我像 "no response" 这样单击 "start" 按钮时,我的 GUI 在 3-4 秒后开始冻结。当我一直点击应用程序时,它被强制关闭。
现在我想阻止这种情况,但我不知道该怎么做。据我所知,单线程中的 JavaFX 运行s,因此,要在执行方法时更新我的 TextArea,我需要在另一个线程中 运行 这些方法。
我希望有人能帮助我。
我的项目怎么样?
我得到了一个 FXML、一个 Controller、一个 Handler、一个 Transformer、一个 Writer 和一个 Reader class(在 Handler class 中使用)。
当我单击绑定到控制器中方法的按钮时,将创建一个 Handler 实例,该实例调用 Reader 读取文本文件,转换为字符串列表(逐行) .
此外,线路正在被操纵。在此之后,Writer 用于创建一个新文件并将新操作的行写入此文件。
也允许用户引用多个文件。
我想要的是,每当 reader 开始读取像 "The file ... is being read".
这样的文件时,文本区域就会显示
然后在 Transformer 开始运行时附加 "The file ... is being manipulated",然后附加
"The file ... is being written" 当新行写入新文件时。
这是一些代码..
控制器:
public class FXMLDocumentController implements Initializable {
@FXML
private TextArea console;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
Handler hand = new Handler();
hand.handle(files);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
处理程序:
public class Handler {
public void handle(List<String> files) {
for (String s : files) {
List<String> ls = Reader.readFile(s);
Writer.writeFile(Transformer.transform(ls));
}
}
我应该如何更改我的代码以在读取、操作或写入文件时更新 TextArea?
Info:我知道 class 处理程序不会编译,因为我删除了列表的初始化 "files" 其中包含文件路径字符串。
如果我遗漏了相关信息,请随时询问。
我先谢谢你了!
您应该在后台线程中执行 handle()
方法:
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
Thread thread = new Thread(() -> {
Handler hand = new Handler();
hand.handle(files);
});
// this line means the background thread will not prevent application exit:
thread.setDaemon(true);
thread.start();
}
如果您想使用当前状态更新文本区域,您需要使用 Platform.runLater()
将其安排回 FX 应用程序线程。可能最简洁的方法是不要在 Handler
class 中使用 Platform.runLater()
,而是在 Handler
中为 "consuming" 状态消息定义一个字段:
public class Handler {
private final Consumer<String> statusMessageProcessor ;
public Handler(Consumer<String> statusMessageProcessor) {
this.statusMessageProcessor = statusMessageProcessor ;
}
// default processor does nothing:
public Handler() {
this(s -> {});
}
public void handle(List<String> files) {
for (String s : files) {
// similarly for other status updates:
statusMessageProcessor.accept("The file "+s+" is being read");
List<String> ls = Reader.readFile(s);
Writer.writeFile(Transformer.transform(ls));
}
}
}
然后
Handler hand = new Handler() ;
可以变成
Handler hand = new Handler(message ->
Platform.runLater(() -> console.appendText(message + "\n")));
在按钮处理程序方法中。
我发现当我像 "no response" 这样单击 "start" 按钮时,我的 GUI 在 3-4 秒后开始冻结。当我一直点击应用程序时,它被强制关闭。
现在我想阻止这种情况,但我不知道该怎么做。据我所知,单线程中的 JavaFX 运行s,因此,要在执行方法时更新我的 TextArea,我需要在另一个线程中 运行 这些方法。
我希望有人能帮助我。
我的项目怎么样?
我得到了一个 FXML、一个 Controller、一个 Handler、一个 Transformer、一个 Writer 和一个 Reader class(在 Handler class 中使用)。
当我单击绑定到控制器中方法的按钮时,将创建一个 Handler 实例,该实例调用 Reader 读取文本文件,转换为字符串列表(逐行) .
此外,线路正在被操纵。在此之后,Writer 用于创建一个新文件并将新操作的行写入此文件。
也允许用户引用多个文件。
我想要的是,每当 reader 开始读取像 "The file ... is being read".
这样的文件时,文本区域就会显示
然后在 Transformer 开始运行时附加 "The file ... is being manipulated",然后附加
"The file ... is being written" 当新行写入新文件时。
这是一些代码..
控制器:
public class FXMLDocumentController implements Initializable {
@FXML
private TextArea console;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
Handler hand = new Handler();
hand.handle(files);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
处理程序:
public class Handler {
public void handle(List<String> files) {
for (String s : files) {
List<String> ls = Reader.readFile(s);
Writer.writeFile(Transformer.transform(ls));
}
}
我应该如何更改我的代码以在读取、操作或写入文件时更新 TextArea?
Info:我知道 class 处理程序不会编译,因为我删除了列表的初始化 "files" 其中包含文件路径字符串。
如果我遗漏了相关信息,请随时询问。
我先谢谢你了!
您应该在后台线程中执行 handle()
方法:
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
Thread thread = new Thread(() -> {
Handler hand = new Handler();
hand.handle(files);
});
// this line means the background thread will not prevent application exit:
thread.setDaemon(true);
thread.start();
}
如果您想使用当前状态更新文本区域,您需要使用 Platform.runLater()
将其安排回 FX 应用程序线程。可能最简洁的方法是不要在 Handler
class 中使用 Platform.runLater()
,而是在 Handler
中为 "consuming" 状态消息定义一个字段:
public class Handler {
private final Consumer<String> statusMessageProcessor ;
public Handler(Consumer<String> statusMessageProcessor) {
this.statusMessageProcessor = statusMessageProcessor ;
}
// default processor does nothing:
public Handler() {
this(s -> {});
}
public void handle(List<String> files) {
for (String s : files) {
// similarly for other status updates:
statusMessageProcessor.accept("The file "+s+" is being read");
List<String> ls = Reader.readFile(s);
Writer.writeFile(Transformer.transform(ls));
}
}
}
然后
Handler hand = new Handler() ;
可以变成
Handler hand = new Handler(message ->
Platform.runLater(() -> console.appendText(message + "\n")));
在按钮处理程序方法中。