Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing user input on Image JavaFX

Tags:

javafx

Suppose you have an app that displays user graphic (some kind of image) then you want to allow the user to draw some lines on this image. I have the following questions regarding such situation:

How would you accomplish that? How would you get pixel coordinates for the image from the user drag events? How would you update the image in real time?

like image 564
CodeSamurai777 Avatar asked Jul 10 '14 15:07

CodeSamurai777


2 Answers

I will give you an example of the exact opposite [erasing the Image on JavaFX] which I suppose will be enough as a starter point for you:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class EraseImageonCanvas extends Application {
    private Pane root = new Pane();
    private void setCanvas(Canvas canvas, Image img) {
        GraphicsContext gc = canvas.getGraphicsContext2D();
        gc.drawImage(img, 0, 0,canvas.getWidth(), canvas.getHeight());
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Erasing the Image");
        Rectangle rect = new Rectangle(400, 400);
        drawBackground(rect);
        root.getChildren().add(rect);
        final Canvas canvas = new Canvas(200, 200);
        canvas.setTranslateX(100);
        canvas.setTranslateY(100);
        //For local images use         
        //image = new Image(getClass().getResource(#Path#).openStream());
        final Image image = new Image(
                "http://kyllo.com.br/wp-content/uploads/2013/12/Faroeste-Cabloco.jpg"
              );
        setCanvas(canvas,image);
        final GraphicsContext gc = canvas.getGraphicsContext2D();
        // Clear away portions as the user drags the mouse
        canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent e) {
                gc.clearRect(e.getX() - 2, e.getY() - 2, 5, 5);
            }
        });

        // Reset the Canvas when the user double-clicks
        canvas.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent t) {            
                if (t.getClickCount() >1) {
                    setCanvas(canvas, image);
                }  
            }
        });

        // Add the Canvas to the Scene, and show the Stage
        root.getChildren().add(canvas);
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }

     //Draws the background with a RadialGradient 
    private void drawBackground(Rectangle rect) {
        rect.setFill(new LinearGradient(0, 0, 1, 1, true,
                CycleMethod.REFLECT,
                new Stop(0, Color.RED),
                new Stop(1, Color.YELLOW)));
    }
    public static void main(String[] args) {
        launch(args);
    }
}

Download it on gist

like image 150
Mansueli Avatar answered Nov 15 '22 07:11

Mansueli


this Canvas tutorial by Oracle shows exactly what you want to accomplish in the "Interacting with the User" section.

It shows how you can add an EventHandler to the Canvas to handle MouseEvent such as MouseEvent.MOUSE_DRAGGED. The GraphicsContext is then used to get the x and y coordinates and draw on the canvas.

In order to use the Canvas outside the main Application class, you'd declare the Canvas in your .fxml file as such:

<BorderPane fx:controller="controllers.MyController" 
  xmlns:fx="http://javafx.com/fxml">
    <Canvas fx:id="drawArea" height="..." width="..."/>
</BorderPane>

Then, on your MyController class:

public class MyController implements Initializable {
  @FXML
  private Canvas drawArea;
  private GraphicsContext gc;

  @Override
  public void initialize(URL location, ResourceBundle resources) {
    gc = drawArea.getGraphicsContext2D();
    // Java 8 syntax, beware!
    drawArea.setOnMouseDragged(event -> gc.fillRect(event.getX(), event.getY(), 5, 5));
  }
}
like image 22
Tarek Avatar answered Nov 15 '22 07:11

Tarek