问题描述
简单的问题,但它一直让我发疯。
Simple enough problem but it's been driving me crazy.
在我的程序中,我有 TextArea
,定义为:
In my program I have a TextArea
, defined as:
<TextArea fx:id="output" editable="false" prefHeight="300.0" prefWidth="200.0" text="Output" GridPane.columnSpan="2" GridPane.rowIndex="4" />
@FXML private TextArea output;
...
public void initialize(URL url, ResourceBundle rb) {
output.setText("Test"); //Test appears correctly in output
...
}
@FXML
public void download() {
String outputTemplate = templateField.getText();
String url = urlField.getText();
System.out.println("Downloading from " + url);
try {
Process down = Runtime.getRuntime().exec("youtube-dl -o \"" + outputTemplate + "\" " + url);
BufferedReader reader = new BufferedReader(new InputStreamReader(down.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line); //Prints as expected
output.appendText(line + "\n"); //Has no effect
}
} catch (IOException e) {
e.printStackTrace();
}
}
有关如何显示文字的任何想法都会很棒,我之前已经在不同的程序上完成了这个,只是出于某种原因,这次它是非常好的
Any ideas on how to get the text to appear would be great, I've done this before on different programs, just for some reason, this time it's being cantankerous
编辑:进一步修改后,它实际上将打印出来结果,但只有在 Process
结束并退出循环之后。
Upon further tinkering, it actually will print out the results, but only after the Process
ends and it exits the loop.
推荐答案
UI中显示的文字在布局脉冲上发生变化。布局脉冲在JavaFX应用程序线程上完成。事件处理程序(如 download
方法)在同一个线程上运行,有效地阻止它在完成之前进行任何布局或处理以及其他事件。这就是为什么你不应该使用longrunning任务来阻止这个线程,而是在不同的线程上执行它们。
The text shown in the UI changes on a layout pulse. Layout pulses are done on the JavaFX application thread. Event handlers, like your download
method run on the same thread effectively preventing it from doing any layouting or processing and other events until it completes. This is why you shouldn't block this thread with longrunning tasks, but execute them on a different thread.
由于UI的更新应该从应用程序线程完成,使用 Platform.runLater
附加文字:
Since updates to the UI should be done from the application thread, use Platform.runLater
to append the text:
@FXML
public void download() {
String outputTemplate = templateField.getText();
String url = urlField.getText();
Runnable r = () -> {
System.out.println("Downloading from " + url);
try {
Process down = Runtime.getRuntime().exec("youtube-dl -o \"" + outputTemplate + "\" " + url);
BufferedReader reader = new BufferedReader(new InputStreamReader(down.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line); //Prints as expected
final String printText = line + "\n";
// append the line on the application thread
Platform.runLater(() -> output.appendText(printText));
}
} catch (IOException e) {
e.printStackTrace();
}
};
// run task on different thread
Thread t = new Thread(r);
t.start();
}
这篇关于JavaFX TextArea appendText适用于初始化,但不适用于其他地方的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!