JavaFX 中带睡眠的 Settext
Settext with sleeps in JavaFX
我想通过一个字符一个字符地写入数据来设置标签的文本。
至此代码为
public void texting(String inc) {
String a = "";
try {
for (char c : inc.toCharArray()) {
a = a + String.valueOf(c);
labelHeader.setText(a);
System.out.println(a);
Thread.sleep(300);
}
} catch (InterruptedException e) {
}
}
控制台显示的文本完全符合我的预期(一个字符一个字符地显示),但是标签会等待过程结束,然后在字符之间没有延迟地显示数据。
可能是什么原因,我该如何解决?
您正在使用 Thread.sleep()
阻止 FX 应用程序线程。这是管理所有 ui 更新的线程,包括呈现 UI 和处理用户输入。由于您阻止了此线程,因此您阻止了它执行正常工作。
相反,您需要在后台线程中执行 "wait" 操作,或者使用某种计时器来管理它。最简单的方法可能是使用 aminmation API 来实现定时器。
所以你可以这样做:
public void texting(String inc) {
IntegerProperty textLength = new IntegerProperty();
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(300)), e -> {
textLength.set(textLength.get()+1);
labelHeader.setText(inc.substring(0, textLength.get()));
});
timeline.setCycleCount(inc.length());
timeline.play();
}
一个细微的变化是创建一个执行一次的时间线并操纵您提取的子字符串的长度:
public void texting(String inc) {
IntegerProperty textLength = new IntegerProperty();
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(300 * inc.length())),
new KeyValue(textLength, inc.length()));
labelHeader.textProperty().bind(Bindings.createStringBinding(() ->
inc.substring(0, textLength.get()), textLength));
timeline.play();
}
如果你想用线程来做这个,你必须做类似的事情:
public void texting(String inc) {
Thread t = new Thread(() -> {
try {
for (int i = 1; i <= inc.length(); i++) {
String text = inc.substring(0, i);
Platform.runLater(() -> labelHeader.setText(text));
Thread.sleep(300);
}
} catch (InterruptedException exc) {
exc.printStackTrace();
}
});
t.setDaemon(true); // thread will not stop application exit
t.start();
}
还有其他各种选择...
我想通过一个字符一个字符地写入数据来设置标签的文本。
至此代码为
public void texting(String inc) {
String a = "";
try {
for (char c : inc.toCharArray()) {
a = a + String.valueOf(c);
labelHeader.setText(a);
System.out.println(a);
Thread.sleep(300);
}
} catch (InterruptedException e) {
}
}
控制台显示的文本完全符合我的预期(一个字符一个字符地显示),但是标签会等待过程结束,然后在字符之间没有延迟地显示数据。
可能是什么原因,我该如何解决?
您正在使用 Thread.sleep()
阻止 FX 应用程序线程。这是管理所有 ui 更新的线程,包括呈现 UI 和处理用户输入。由于您阻止了此线程,因此您阻止了它执行正常工作。
相反,您需要在后台线程中执行 "wait" 操作,或者使用某种计时器来管理它。最简单的方法可能是使用 aminmation API 来实现定时器。
所以你可以这样做:
public void texting(String inc) {
IntegerProperty textLength = new IntegerProperty();
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(300)), e -> {
textLength.set(textLength.get()+1);
labelHeader.setText(inc.substring(0, textLength.get()));
});
timeline.setCycleCount(inc.length());
timeline.play();
}
一个细微的变化是创建一个执行一次的时间线并操纵您提取的子字符串的长度:
public void texting(String inc) {
IntegerProperty textLength = new IntegerProperty();
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(300 * inc.length())),
new KeyValue(textLength, inc.length()));
labelHeader.textProperty().bind(Bindings.createStringBinding(() ->
inc.substring(0, textLength.get()), textLength));
timeline.play();
}
如果你想用线程来做这个,你必须做类似的事情:
public void texting(String inc) {
Thread t = new Thread(() -> {
try {
for (int i = 1; i <= inc.length(); i++) {
String text = inc.substring(0, i);
Platform.runLater(() -> labelHeader.setText(text));
Thread.sleep(300);
}
} catch (InterruptedException exc) {
exc.printStackTrace();
}
});
t.setDaemon(true); // thread will not stop application exit
t.start();
}
还有其他各种选择...