java thread 更新ui_从JavaFX中的不同线程更新UI

的计数速度最快,它会更新IntegerProperty。观察者监视该属性,并使用新值更新AtomicInteger。如果AtomicInteger的当前值为-1,它将调度Platform.runLater()。

在Platform.runLater中,我检索AtomicInteger的值并使用它来更新Label,在此过程中将该值设置回-1。这表明我已准备好进行另一个UI更新。

import java.text.NumberFormat;

import java.util.concurrent.atomic.AtomicInteger;

import javafx.application.Application;

import javafx.application.Platform;

import javafx.beans.property.IntegerProperty;

import javafx.beans.property.SimpleIntegerProperty;

import javafx.beans.value.ChangeListener;

import javafx.beans.value.ObservableValue;

import javafx.event.ActionEvent;

import javafx.event.EventHandler;

import javafx.scene.Scene;

import javafx.scene.control.Button;

import javafx.scene.control.Label;

import javafx.scene.layout.AnchorPane;

import javafx.stage.Stage;

public class ConcurrentModel extends Application {

@Override

public void start(Stage primaryStage) {

final AtomicInteger count = new AtomicInteger(-1);

final AnchorPane root = new AnchorPane();

final Label label = new Label();

final Model model = new Model();

final NumberFormat formatter = NumberFormat.getIntegerInstance();

formatter.setGroupingUsed(true);

model.intProperty().addListener(new ChangeListener() {

@Override

public void changed(final ObservableValue extends Number> observable,

final Number oldValue, final Number newValue) {

if (count.getAndSet(newValue.intValue()) == -1) {

Platform.runLater(new Runnable() {

@Override

public void run() {

long value = count.getAndSet(-1);

label.setText(formatter.format(value));

}

});

}

}

});

final Button startButton = new Button("Start");

startButton.setOnAction(new EventHandler() {

@Override

public void handle(ActionEvent event) {

model.start();

}

});

AnchorPane.setTopAnchor(label, 10.0);

AnchorPane.setLeftAnchor(label, 10.0);

AnchorPane.setBottomAnchor(startButton, 10.0);

AnchorPane.setLeftAnchor(startButton, 10.0);

root.getChildren().addAll(label, startButton);

Scene scene = new Scene(root, 100, 100);

primaryStage.setScene(scene);

primaryStage.show();

}

public static void main(String[] args) {

launch(args);

}

public class Model extends Thread {

private IntegerProperty intProperty;

public Model() {

intProperty = new SimpleIntegerProperty(this, "int", 0);

setDaemon(true);

}

public int getInt() {

return intProperty.get();

}

public IntegerProperty intProperty() {

return intProperty;

}

@Override

public void run() {

while (true) {

intProperty.set(intProperty.get() + 1);

}

}

}

}

如果您确实想从UI“驱动”后端:即限制后端实现的速度,以便查看所有更新,请考虑使用AnimationTimer。一个AnimationTimer具有handle(...)每帧一次渲染被调用。因此,您可以阻塞后端实现(例如,通过使用阻塞队列),并在每次调用handle方法时将其释放一次。该handle(...)方法在FX Application Thread上调用。

该handle(...)方法采用的参数是时间戳(以纳秒为单位),因此如果每帧一次过快,则可以使用该参数进一步减慢更新速度。

例如:

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.BlockingQueue;

import javafx.animation.AnimationTimer;

import javafx.application.Application;

import javafx.beans.property.LongProperty;

import javafx.beans.property.SimpleLongProperty;

import javafx.geometry.Insets;

import javafx.geometry.Pos;

import javafx.stage.Stage;

import javafx.scene.Scene;

import javafx.scene.control.Button;

import javafx.scene.control.TextArea;

import javafx.scene.layout.BorderPane;

import javafx.scene.layout.HBox;

public class Main extends Application {

@Override

public void start(Stage primaryStage) {

final BlockingQueue messageQueue = new ArrayBlockingQueue<>(1);

TextArea console = new TextArea();

Button startButton = new Button("Start");

startButton.setOnAction(event -> {

MessageProducer producer = new MessageProducer(messageQueue);

Thread t = new Thread(producer);

t.setDaemon(true);

t.start();

});

final LongProperty lastUpdate = new SimpleLongProperty();

final long minUpdateInterval = 0 ; // nanoseconds. Set to higher number to slow output.

AnimationTimer timer = new AnimationTimer() {

@Override

public void handle(long now) {

if (now - lastUpdate.get() > minUpdateInterval) {

final String message = messageQueue.poll();

if (message != null) {

console.appendText("\n" + message);

}

lastUpdate.set(now);

}

}

};

timer.start();

HBox controls = new HBox(5, startButton);

controls.setPadding(new Insets(10));

controls.setAlignment(Pos.CENTER);

BorderPane root = new BorderPane(console, null, null, controls, null);

Scene scene = new Scene(root,600,400);

primaryStage.setScene(scene);

primaryStage.show();

}

private static class MessageProducer implements Runnable {

private final BlockingQueue messageQueue ;

public MessageProducer(BlockingQueue messageQueue) {

this.messageQueue = messageQueue ;

}

@Override

public void run() {

long messageCount = 0 ;

try {

while (true) {

final String message = "Message " + (++messageCount);

messageQueue.put(message);

}

} catch (InterruptedException exc) {

System.out.println("Message producer interrupted: exiting.");

}

}

}

public static void main(String[] args) {

launch(args);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值