1

So this are my first steps with JavaFX, I'm trying to create a simple desktop application in JavaFx which emulates a real time kind of bar chart, refreshing every second to add the portion of the bar that represents the status of every sensor (off, not working, working ok...). I have to implement some buttons/textfields/menuItems for sending information to both sensor and application.

So I'm using a method which is called from start() method just before adding the canvas to the scene, from where I invoke a TimerTask to draw the graph every second, and it works fine. With this, when I try to set this canvas in the center of a BorderPane, and add the other elements to another part of the pane, the working of them is affected by the delay of the TimerTask, even when this timerTask is supposedly executed by a different thread.

How could I separate the real time drawing from the rest of the application in different threads?? Should I use another class different from "TimerTask"??

The code is something like this:

@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);
}
4

1 回答 1

0

你可以看看这个答案:

JavaFX 周期性后台任务

使用 aTimerTask是可以的。您应该使用计时器线程(后台线程)将您的请求调用到外部服务并使用 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);
于 2015-03-10T10:55:19.043 回答