Drawing user input on Image JavaFX

2020-07-22 17:53发布

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?

标签: javafx
2条回答
该账号已被封号
2楼-- · 2020-07-22 18:44

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

查看更多
兄弟一词,经得起流年.
3楼-- · 2020-07-22 18:46

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));
  }
}
查看更多
登录 后发表回答