0

I am trying to do a neural network training visualization with JavaFX 8. The network cells are shown as dots changing their color depending on the output value. The calculations and the drawing are done in a thread that can be started or stopped by clicking a button. For a while everything works fine but after a number of iterations the display is no longer updated.

What needs to be done to reliably update the display?

I am using JRE version 1.8.0_45.

Here's a simplified version of my code:

import javafx.application.*;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.*;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;

public class TestView extends Application {

    public static final int SCENE_WIDTH = 1000;
    public static final int SCENE_HEIGHT = 800;
    public static final int BUTTON_PANEL_HEIGHT = 80;

    private Canvas canvas;
    private GraphicsContext gc;
    private Task<Void> task = null;

    public static void main(String[] args) {

        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        primaryStage.setTitle("MLP");
        BorderPane borderPane = new BorderPane();

        canvas = new Canvas( SCENE_WIDTH, 3*SCENE_HEIGHT-BUTTON_PANEL_HEIGHT );     
        gc = canvas.getGraphicsContext2D();
        borderPane.setCenter(new ScrollPane(canvas));

        GridPane buttonPanel = new GridPane();

        Button buttonTrain = new Button("Train");
        buttonTrain.setMinWidth(SCENE_WIDTH/2);
        buttonPanel.setPadding(new Insets(0, 0, 0, 0));
        buttonPanel.add(buttonTrain, 1, 0);

        borderPane.setBottom(buttonPanel);

        buttonTrain.setOnMouseClicked( e -> { 
            if (task != null) {
                task.cancel();
                task = null;
            }
            else {
                task = new Task<Void>() {
                    @Override
                    protected Void call() throws Exception {
                        for (int i = 1; i <= 10000000; i++) {
                            if (isCancelled()) {
                                break;
                            }

                            // dummy calculation
                            doSomeStuff();

                            // dummy graphics update
                            gc.setFill(Color.GREEN);
                            gc.fillOval(50, 50, 20, 20);
                            gc.clearRect(200, 10, 200, 100);
                            gc.setFill(Color.BLACK);
                            gc.fillText("" + i, 200, 50);
                        }
                        return null;
                    }
                };

                new Thread(task).start();
            }
        });

        Scene scene = new Scene( borderPane, SCENE_WIDTH, SCENE_HEIGHT );
        primaryStage.setScene(scene);
        primaryStage.show();
    }


    private double doSomeStuff() {
        double r = 0.5;
        for ( int i = 0; i < 10000; i++ ) {
            r = Math.sin(r);
        }
        return r;
    }
}
Frank Puffer
  • 8,135
  • 2
  • 20
  • 45
  • 3
    You're updating the UI from a thread other than the FX Application Thread. Behavior is not defined when you do that. – James_D Mar 04 '17 at 23:24
  • 1
    I rarely use JavaFX canvas, so I am not sure about this, but I think you are also concatenating more and more commands to the graphics context's stack. You may need to clear the gc each time. – James_D Mar 04 '17 at 23:41
  • @James_D: Yes, this seems to be the issue. I learned that there is a [pulse](https://docs.oracle.com/javase/8/javafx/get-started-tutorial/jfx-architecture.htm) event in JavaFX that is fired 60 times per second and that is resposible for updating the display. Inserting a `Thread.sleep(50)` into my loop has resolved the issue. Still I am wondering if there might be a better solution. – Frank Puffer Mar 05 '17 at 09:41
  • 1
    Yes read http://stackoverflow.com/questions/22772379/updating-ui-from-different-threads-in-javafx for example – Jean-Baptiste Yunès Mar 05 '17 at 09:45

0 Answers0