Javafx canvas draw only moving object without redraw the background


Question

I am drawing inside JavaFx Canvas the program draw many different shapes and one of them represent a position marker(Oval) in some situation its position must be updated every 1 second and this is OK to remove several traces of marker I have to redraw again and this slow the program the question how can I redraw only the current marker removing its traces without drawing all shapes?? much like swing repaint() .

import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;



public class  DrawChart    { 

private Timeline timelinePosition;
private Canvas canvas;
private GraphicsContex graphicsContex;



public void start()  {

  canvas = new Canvas();
  graphicsContex = canvas.getGraphicsContext2D();
  drawManyShapes();
  drawPositionMarker();
  someStateMonitor();

}

public void drawManyShapes()  {


     draw many shapes .......
}

public void drawPositionMarker()  {


        EventHandler eventHandler = new EventHandler<ActionEvent>() {
            public void handle(ActionEvent t) {

                graphicsContex.strokeOval(posi_x , posi_y,  width , hight );    



            }
        };

        Duration duration = Duration.millis(1000);

        timelinePosition = new Timeline();
        timelinePosition.setDelay(duration);
        timelinePosition.setCycleCount(Timeline.INDEFINITE);
        KeyFrame keyPosition = new KeyFrame(duration, drawPosition , null, null);
        timelinePosition.getKeyFrames().add(keyPosition);



    }


public void someStateMonitor()  {

  if(state == true) timelinePosition.play();
  if(state == false) timelinePosition.stop();


}


    }
1
2
7/20/2014 1:27:28 PM

Accepted Answer

You can add layers of canvases. Or you can save a rectangle under your shape and redraw that after.

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class LayeredCanvas extends Application {

    @Override
    public void start(Stage primaryStage) {
        Canvas layer1 = new Canvas(700, 300);
        Canvas layer2 = new Canvas(700, 300);
        GraphicsContext gc1 = layer1.getGraphicsContext2D();
        GraphicsContext gc2 = layer2.getGraphicsContext2D();

        gc1.setFill(Color.GREEN);
        gc1.setFont(new Font("Comic sans MS", 100));
        gc1.fillText("BACKGROUND", 0, 100);
        gc1.fillText("LAYER", 0, 200);
        gc1.setFont(new Font(30));
        gc1.setFill(Color.RED);
        gc1.fillText("Hold a key", 0, 270);

        gc2.setFill(Color.BLUE);
        Pane root = new Pane(layer1, layer2);
        Scene scene = new Scene(root);

        primaryStage.setScene(scene);
        primaryStage.show();

        scene.setOnKeyPressed((evt) -> {
            gc2.clearRect(0, 0, layer2.getWidth(), layer2.getHeight());
            gc2.fillOval(Math.random() * layer2.getWidth(), Math.random() * layer2.getHeight(), 20, 30);
        });
    }

    public static void main(String[] args) {
        launch(args);
    }

}
2
7/20/2014 10:34:29 PM

I have encountered this issue as well (for me rectangle) and I made a rectangle class, you could to the same but with ovals. The example is just to give you a idea

class Rectangle {
//x position
int x;
//y position
int y;
//size for width
int xSize;
//size for height
int ySize;
//to draw on the canvas
GraphicsContext graphics;

//used to create a rectangle object
public Rectangle(GraphicsContext graphics, int x, int y, int xSize, int ySize) {
    //sets fields used for the rectangle
    this.x = x;
    this.y = y;
    this.xSize = xSize;
    this.ySize = ySize;
    this.graphics = graphics;

        graphics.fillRect(x, y, xSize, ySize);
}

    //used to get rid of rectangles
public void delete(Rectangle rectangle) {
    //erase the rectangle
    (rectangle.graphics).clearRect(rectangle.x, rectangle.y, rectangle.xSize, rectangle.ySize);

    //erase its fields
    rectangle.x = -1;
    rectangle.y = -1;
    rectangle.xSize = -1;
    rectangle.ySize = -1;
}

//will redraw the rectangle
public void reDraw(Rectangle rectangle) {
    (rectangle.graphics).fillRect(rectangle.x, rectangle.y, rectangle.xSize, rectangle.ySize);
}

//will move the rectangle
public void move(Rectangle rectangle, int x, int y) {
    (rectangle.graphics).clearRect(rectangle.x, rectangle.y, rectangle.xSize+1, rectangle.ySize+1);

        (rectangle.graphics).fillRect(x, y, rectangle.xSize, rectangle.ySize);
    }
    //redifine the fields
    this.x = x;
    this.y = y; } }

You could add other fields as well.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon