JavaFX 中实时图形和其余元素的并发性?
Concurrency of real time graphics and rest of elements in JavaFX?
所以这是我使用 JavaFX 的第一步,我正在尝试在 JavaFx 中创建一个简单的桌面应用程序,它模拟一种实时条形图,每秒刷新一次以添加代表状态的条形部分每个传感器(关闭,不工作,工作正常......)。我必须实施一些 buttons/textfields/menuItems 来向传感器和应用程序发送信息。
所以我正在使用一种方法,该方法是在将 canvas 添加到场景之前从 start() 方法调用的,从那里我调用了 TimerTask 每秒绘制图形,效果很好。有了这个,当我尝试将此 canvas 设置在 BorderPane 的中心并将其他元素添加到窗格的另一部分时,它们的工作受到影响TimerTask 的延迟,即使这个 timerTask 应该由不同的线程执行。
如何在不同线程中将实时绘图与应用程序的其余部分分开?我应该使用不同于 "TimerTask" 的另一个 class 吗??
代码是这样的:
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
BorderPane bp = new BorderPane();
Group root = new Group();
// create a canvas node
Canvas canvas = new Canvas();
// bind the dimensions when the user resizes the window.
canvas.widthProperty().bind(primaryStage.widthProperty());
canvas.heightProperty().bind(primaryStage.heightProperty());
// obtain the GraphicsContext (drawing surface)
final GraphicsContext gc = canvas.getGraphicsContext2D();
//Invoke the real time graph drawing
draw(gc);
// add the single node onto the border pane
bp.setCenter(canvas);
MenuBar bar = new MenuBar();
Menu sensorsMenu = new Menu("Sensors");
bar.getMenus().add(sensors);
for(int i=0; i<nDetect; i++){
sensorsMenu.getItems().add(new CheckMenuItem("Sensor " + (i+1)));
}
//add the menu bar to top
bp.setTop(bar);
root.getChildren().add(bp);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public void draw(GraphicsContext gc){
c = new SerialPortConection();
c.establishConnection("COM1", 2400, 8, 1, 1);
LinkedList<String> resp = null;
.
.
.
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
javafx.application.Platform.runLater(new Runnable() {
@Override
public void run() {
//Send request to sensor
try {
resp = c.sendStatusRequest();
} catch (WrongFormatException ex) {
Logger.getLogger(Sensor.class.getName()).log(Level.SEVERE, null, ex);
}
//Update sensor status
for(int i=0; i<nSensors; i++){
sensors.get(i).update(resp.get(37+i));
}
//Draw sensors status
for(int i=0; i<nSensors; i++){
sensors.get(i).draw(gc);
}
//Paint axis
.
.
.
}
});
}
}, 0, 1000);
}
你可以看看这个答案:
JavaFX periodic background task
使用 TimerTask
即可。您应该使用定时器线程(后台线程)来调用您对外部服务的请求,并使用 JFX 线程来更新图形:
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// call external service in the background thread
resp = c.sendStatusRequest();
javafx.application.Platform.runLater(new Runnable() {
@Override
public void run() {
// update the graphics in the JFX thread
}
});
}
}, 0, 1000);
所以这是我使用 JavaFX 的第一步,我正在尝试在 JavaFx 中创建一个简单的桌面应用程序,它模拟一种实时条形图,每秒刷新一次以添加代表状态的条形部分每个传感器(关闭,不工作,工作正常......)。我必须实施一些 buttons/textfields/menuItems 来向传感器和应用程序发送信息。
所以我正在使用一种方法,该方法是在将 canvas 添加到场景之前从 start() 方法调用的,从那里我调用了 TimerTask 每秒绘制图形,效果很好。有了这个,当我尝试将此 canvas 设置在 BorderPane 的中心并将其他元素添加到窗格的另一部分时,它们的工作受到影响TimerTask 的延迟,即使这个 timerTask 应该由不同的线程执行。
如何在不同线程中将实时绘图与应用程序的其余部分分开?我应该使用不同于 "TimerTask" 的另一个 class 吗??
代码是这样的:
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
BorderPane bp = new BorderPane();
Group root = new Group();
// create a canvas node
Canvas canvas = new Canvas();
// bind the dimensions when the user resizes the window.
canvas.widthProperty().bind(primaryStage.widthProperty());
canvas.heightProperty().bind(primaryStage.heightProperty());
// obtain the GraphicsContext (drawing surface)
final GraphicsContext gc = canvas.getGraphicsContext2D();
//Invoke the real time graph drawing
draw(gc);
// add the single node onto the border pane
bp.setCenter(canvas);
MenuBar bar = new MenuBar();
Menu sensorsMenu = new Menu("Sensors");
bar.getMenus().add(sensors);
for(int i=0; i<nDetect; i++){
sensorsMenu.getItems().add(new CheckMenuItem("Sensor " + (i+1)));
}
//add the menu bar to top
bp.setTop(bar);
root.getChildren().add(bp);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public void draw(GraphicsContext gc){
c = new SerialPortConection();
c.establishConnection("COM1", 2400, 8, 1, 1);
LinkedList<String> resp = null;
.
.
.
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
javafx.application.Platform.runLater(new Runnable() {
@Override
public void run() {
//Send request to sensor
try {
resp = c.sendStatusRequest();
} catch (WrongFormatException ex) {
Logger.getLogger(Sensor.class.getName()).log(Level.SEVERE, null, ex);
}
//Update sensor status
for(int i=0; i<nSensors; i++){
sensors.get(i).update(resp.get(37+i));
}
//Draw sensors status
for(int i=0; i<nSensors; i++){
sensors.get(i).draw(gc);
}
//Paint axis
.
.
.
}
});
}
}, 0, 1000);
}
你可以看看这个答案:
JavaFX periodic background task
使用 TimerTask
即可。您应该使用定时器线程(后台线程)来调用您对外部服务的请求,并使用 JFX 线程来更新图形:
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// call external service in the background thread
resp = c.sendStatusRequest();
javafx.application.Platform.runLater(new Runnable() {
@Override
public void run() {
// update the graphics in the JFX thread
}
});
}
}, 0, 1000);