【问题标题】:How to draw a continuous line with mouse on JavaFX canvas?如何在 JavaFX 画布上用鼠标绘制连续线?
【发布时间】:2017-09-11 18:13:08
【问题描述】:

下面的代码生成了一个 JavaFX 画布,它可以用鼠标指针在上面绘制,但会跳过一些点,即,如果尝试绘制一条连续的线,则会留下空隙。随着指针速度的增加,间隙会加剧。

是什么导致了这种行为以及如何实现连接良好的线? (注意,我正在寻找一个答案,明确切换指针经过的每个像素变黑,不是平滑或连接点等操作)

public class DrawingSample extends Application {
    public void start(Stage stage) {
        FlowPane flowPane = new FlowPane();
        Canvas canvas = new Canvas(300, 300);
        flowPane.getChildren().add(canvas);
        GraphicsContext graphicsContext = canvas.getGraphicsContext2D();

        graphicsContext.setFill(Color.WHITE);
        graphicsContext.fillRect(0, 0, 300, 300);

        canvas.setOnMouseDragged((event) -> {
            graphicsContext.setFill(Color.BLACK);
            graphicsContext.fillRect(event.getX(), event.getY(), 1, 1);
        });

        stage.setScene(new Scene(flowPane));
        stage.show();
    }

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

下图展示了随着我们下降,从左到右以增加速度绘制的三条线。

【问题讨论】:

    标签: java canvas javafx


    【解决方案1】:

    此代码来自here

    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.input.MouseEvent;
    import javafx.scene.layout.StackPane;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    
    /**
     * @web http://java-buddy.blogspot.com/
     */
    public class JavaFX_DrawOnCanvas extends Application {
    
        @Override
        public void start(Stage primaryStage) {
    
            Canvas canvas = new Canvas(400, 400);
            final GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
            initDraw(graphicsContext);
    
            canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, 
                    new EventHandler<MouseEvent>(){
    
                @Override
                public void handle(MouseEvent event) {
                    graphicsContext.beginPath();
                    graphicsContext.moveTo(event.getX(), event.getY());
                    graphicsContext.stroke();
                }
            });
    
            canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, 
                    new EventHandler<MouseEvent>(){
    
                @Override
                public void handle(MouseEvent event) {
                    graphicsContext.lineTo(event.getX(), event.getY());
                    graphicsContext.stroke();
                }
            });
    
            canvas.addEventHandler(MouseEvent.MOUSE_RELEASED, 
                    new EventHandler<MouseEvent>(){
    
                @Override
                public void handle(MouseEvent event) {
    
                }
            });
    
            StackPane root = new StackPane();
            root.getChildren().add(canvas);
            Scene scene = new Scene(root, 400, 400);
            primaryStage.setTitle("java-buddy.blogspot.com");
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
        private void initDraw(GraphicsContext gc){
            double canvasWidth = gc.getCanvas().getWidth();
            double canvasHeight = gc.getCanvas().getHeight();
    
            gc.setFill(Color.LIGHTGRAY);
            gc.setStroke(Color.BLACK);
            gc.setLineWidth(5);
    
            gc.fill();
            gc.strokeRect(
                    0,              //x of the upper left corner
                    0,              //y of the upper left corner
                    canvasWidth,    //width of the rectangle
                    canvasHeight);  //height of the rectangle
    
            gc.setFill(Color.RED);
            gc.setStroke(Color.BLUE);
            gc.setLineWidth(1);
    
        }
    
    }
    

    【讨论】:

    • 我们不能直接使用Line 并在鼠标拖动时更改 endX() 和 endY() 吗?
    • 我对此表示怀疑。 Line 画一条直线。
    • 哦,对不起,我的错,我以为 OP 要求的是直线 :)
    【解决方案2】:

    抱歉之前的消息,应该在新线程中提问,对吧?

    这是一个效果更好的解决方案,不会像上面的 scribbletest 那样创建奇怪的线条。

    canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, 
            new EventHandler<MouseEvent>(){
        @Override
        public void handle(MouseEvent event) {
            graphicsContext.beginPath();
            graphicsContext.moveTo(event.getX(), event.getY());
            graphicsContext.stroke();
    
        }
    });
    
    canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, 
            new EventHandler<MouseEvent>(){
        @Override
        public void handle(MouseEvent event) {
            graphicsContext.lineTo(event.getX(), event.getY());
            graphicsContext.stroke();
            graphicsContext.closePath();
            graphicsContext.beginPath();
            graphicsContext.moveTo(event.getX(), event.getY());
        }
    });
    
    canvas.addEventHandler(MouseEvent.MOUSE_RELEASED, 
            new EventHandler<MouseEvent>(){
        @Override
        public void handle(MouseEvent event) {
            graphicsContext.lineTo(event.getX(), event.getY());
            graphicsContext.stroke();
            graphicsContext.closePath();
        }
    });
    

    【讨论】:

      猜你喜欢
      • 2015-01-04
      • 2015-07-05
      • 1970-01-01
      • 1970-01-01
      • 2020-08-09
      • 1970-01-01
      • 1970-01-01
      • 2012-01-22
      • 1970-01-01
      相关资源
      最近更新 更多