JavaFX - 并发和更新标签
JavaFX - Concurrency and updating label
我对这段代码有疑问。我想制作一个应用程序,只要按下切换按钮,它就会在标签中不断显示随机值。这就是我创建的,它可以工作,但 window 几秒钟后就会出现可怕的延迟。我做错了什么?
这里是class的代码,生成随机值:
public class ValueMaker{
private StringPropterty x, y, z;
private Random generator;
private boolean isStarted = false;
private int randomizedX(){ return generator.nextInt(10); }
private int randomizedY(){ return generator.nextInt(10); }
private int randomizedZ(){ return generator.nextInt(10); }
public StringProperty xProperty(){ return x; }
public StringProperty yProperty(){ return y; }
public StringProperty zProperty() { return z; }
public ValueMaker(){
x = new SimpleStringProperty("0");
y = new SimpleStringProperty("0");
z = new SimpleStringProperty("0");
generator = new Random();
}
private void setValues(){
Platform.runLater(new Runnable() {
@Override
public void run() {
x.set(String.valueOf(randomizedX()));
y.set(String.valueOf(randomizedY()));
z.set(String.valueOf(randomizedZ()));
}
});
}
public startRandomize(){
isStarted = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (isStarted){
setValues();
}
}
});
t.start();
}
public stopRandomize(){
isStarted = false;
}
}
这里是一段控制器代码,它调用了这些方法:
@FXML
private void initialize(){
labelX.textProperty().bind(ValueMaker.xProperty());
labelY.textProperty().bind(ValueMaker.yProperty());
labelZ.textProperty().bind(ValueMaker.zProperty());
startRandomizeButton.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue==true){
ValueMaker.startRandomize();
}
else{
ValueMaker.stopRandomize();
}
}
});
}
我认为当您启动线程时 - 它会使用所有可用资源。它在无限循环中工作并生成随机数而不需要 "break".
尝试将 sleep
添加到线程的循环中,这样它就会暂停几毫秒并稍微释放 CPU。
无论如何你可能需要添加睡眠,否则随机标签会变化太快。
您通过连续调用 Platform.runLater
阻塞了 JavaFX 应用程序线程。实现此目的的最佳方法是使用 AnimationTimer
,它会在每个帧处于活动状态时被调用。
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
x.set(String.valueOf(randomizedX()));
y.set(String.valueOf(randomizedY()));
z.set(String.valueOf(randomizedZ()));
}
};
然后在您的示例中调用计时器:
startRandomizeButton.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
// newValue==true is not required
if (newValue){
timer.start();
}
else{
timer.stop();
}
});
}
我对这段代码有疑问。我想制作一个应用程序,只要按下切换按钮,它就会在标签中不断显示随机值。这就是我创建的,它可以工作,但 window 几秒钟后就会出现可怕的延迟。我做错了什么?
这里是class的代码,生成随机值:
public class ValueMaker{
private StringPropterty x, y, z;
private Random generator;
private boolean isStarted = false;
private int randomizedX(){ return generator.nextInt(10); }
private int randomizedY(){ return generator.nextInt(10); }
private int randomizedZ(){ return generator.nextInt(10); }
public StringProperty xProperty(){ return x; }
public StringProperty yProperty(){ return y; }
public StringProperty zProperty() { return z; }
public ValueMaker(){
x = new SimpleStringProperty("0");
y = new SimpleStringProperty("0");
z = new SimpleStringProperty("0");
generator = new Random();
}
private void setValues(){
Platform.runLater(new Runnable() {
@Override
public void run() {
x.set(String.valueOf(randomizedX()));
y.set(String.valueOf(randomizedY()));
z.set(String.valueOf(randomizedZ()));
}
});
}
public startRandomize(){
isStarted = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (isStarted){
setValues();
}
}
});
t.start();
}
public stopRandomize(){
isStarted = false;
}
}
这里是一段控制器代码,它调用了这些方法:
@FXML
private void initialize(){
labelX.textProperty().bind(ValueMaker.xProperty());
labelY.textProperty().bind(ValueMaker.yProperty());
labelZ.textProperty().bind(ValueMaker.zProperty());
startRandomizeButton.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue==true){
ValueMaker.startRandomize();
}
else{
ValueMaker.stopRandomize();
}
}
});
}
我认为当您启动线程时 - 它会使用所有可用资源。它在无限循环中工作并生成随机数而不需要 "break".
尝试将 sleep
添加到线程的循环中,这样它就会暂停几毫秒并稍微释放 CPU。
无论如何你可能需要添加睡眠,否则随机标签会变化太快。
您通过连续调用 Platform.runLater
阻塞了 JavaFX 应用程序线程。实现此目的的最佳方法是使用 AnimationTimer
,它会在每个帧处于活动状态时被调用。
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
x.set(String.valueOf(randomizedX()));
y.set(String.valueOf(randomizedY()));
z.set(String.valueOf(randomizedZ()));
}
};
然后在您的示例中调用计时器:
startRandomizeButton.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
// newValue==true is not required
if (newValue){
timer.start();
}
else{
timer.stop();
}
});
}