Итак, это мои первые шаги с JavaFX. Я пытаюсь создать простое настольное приложение на JavaFx, которое эмулирует гистограмму в реальном времени, обновляясь каждую секунду, чтобы добавить часть полосы, которая представляет состояние каждого датчика (выключено). , не работает, работает нормально...). Мне нужно реализовать некоторые кнопки/текстовые поля/элементы меню для отправки информации как на датчик, так и на приложение.
Поэтому я использую метод, который вызывается из метода start() непосредственно перед добавлением холста в сцену, откуда я вызываю TimerTask для рисования графика каждую секунду. , и он работает нормально. При этом, когда я пытаюсь установить этот холст в центре BorderPane и добавить другие элементы в другую часть панели, на их работу влияет задержка TimerTask, даже когда этот timerTask предположительно выполняется другим потоком.
Как я могу отделить рисование в реальном времени от остальной части приложения в разных потоках?? Должен ли я использовать другой класс, отличный от «TimerTask»??
Код примерно такой:
@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);
}
resp = c.sendStatusRequest();
может потребоваться некоторое время для выполнения, так как он ожидает запроса. Не так ли? Если да, вы можете убрать его изPlatform.runLater()
, так как вы блокируете поток пользовательского интерфейса, ожидая ответа. Поместив его вPlatform.runLater
, он выполняется в том же потоке пользовательского интерфейса, а не в другом потоке. - person ItachiUchiha   schedule 10.03.2015Platform.runLater
работает. - person ItachiUchiha   schedule 10.03.2015