2016-11-05 73 views
0

我使用JavaFX創建了一個小型繪圖程序。我已經在畫布上成功實現了免費繪圖。不過,我也希望能夠從點擊時直到我的鼠標被壓下時畫出直線。我預先創建了一條線,但是我似乎無法切換上下文,因此我只繪製直線而不是自由繪圖。現在,如果我點擊我的「直線」按鈕,它將繪製一條直線,然後默認返回到自由繪圖,同時拋出很多錯誤。你能幫忙嗎?嘗試在JavaFX中切換GraphicsContext的上下文

這是我的自由繪製代碼:

paintScene.setOnMousePressed(e -> { 
     gc.beginPath(); 
     gc.lineTo(e.getSceneX(), e.getSceneY()); 
     gc.stroke(); 
    }); 

    paintScene.setOnMouseDragged(e -> { 
     gc.lineTo(e.getSceneX(), e.getSceneY()); 
     gc.stroke(); 
    });  

(其中GC是GraphicsContext)

這是我創建直線功能:

Line l = new Line(20, 30, 30, 20); 
    l.setStroke(Color.BLACK); 
    l.setStrokeWidth(10); 

     straightLineBtn.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { 
     @Override 
     public void handle(MouseEvent event) { 
      paintScene.setOnMousePressed(event1 -> { 
       canvasHolder.getChildren().addAll(l); 
      }); 

     } 
    }); 
+0

,你可以創建一個[MCVE(http://stackoverflow.com/help/mcve)我們來測試你的問題嗎? – ItachiUchiha

回答

1

您需要更新行,直到釋放鼠標按鈕。這意味着您必須存儲之前繪製的所有內容的數據,或者需要在畫布上繪製LineNode。我推薦以後的方法。

示例代碼

private static class LineDrawListener implements EventHandler<ActionEvent> { 

    private LineDrawListener(Canvas canvas, Pane canvasPane) { 
     this.canvasPane = canvasPane; 
     this.gc = canvas.getGraphicsContext2D(); 

     line = new Line(); 
     line.setStrokeWidth(10); 
     line.setManaged(true); 
     line.setMouseTransparent(true); 

     releasedHandler = evt -> { 
      // remove line from canvas parent and draw line on canvas instead 
      canvasPane.getChildren().remove(line); 
      Point2D start = canvas.parentToLocal(line.getStartX(), line.getStartY()); 
      Point2D end = canvas.parentToLocal(line.getEndX(), line.getEndY()); 
      gc.setLineWidth(10); 
      gc.strokeLine(start.getX(), start.getY(), end.getX(), end.getY()); 
      removeListeners(); 
     }; 
     draggedHandler = evt -> { 
      // update end of line 
      line.setEndX(evt.getX()); 
      line.setEndY(evt.getY()); 
     }; 
     pressedHandler = evt -> { 
      // add line to canvas parent 
      canvasPane.getChildren().add(line); 
      line.setStartX(evt.getX()); 
      line.setStartY(evt.getY()); 
      line.setEndX(evt.getX()); 
      line.setEndY(evt.getY()); 
     }; 
    } 

    private final GraphicsContext gc; 
    private final Pane canvasPane; 
    private final Line line; 

    private final EventHandler<MouseEvent> pressedHandler; 

    private final EventHandler<MouseEvent> draggedHandler; 

    private final EventHandler<MouseEvent> releasedHandler; 

    private void removeListeners() { 
     canvasPane.setOnMousePressed(null); 
     canvasPane.setOnMouseDragged(null); 
     canvasPane.setOnMouseReleased(null); 
    } 

    @Override 
    public void handle(ActionEvent event) { 
     canvasPane.setOnMousePressed(pressedHandler); 
     canvasPane.setOnMouseDragged(draggedHandler); 
     canvasPane.setOnMouseReleased(releasedHandler); 
    } 

} 

@Override 
public void start(Stage primaryStage) { 
    Canvas canvas = new Canvas(400, 400); 

    Rectangle clip = new Rectangle(); 
    clip.widthProperty().bind(canvas.widthProperty()); 
    clip.heightProperty().bind(canvas.heightProperty()); 

    Pane canvasPane = new Pane(canvas); 
    canvasPane.setClip(clip); 

    Button btn = new Button("Draw Line"); 
    LineDrawListener listener = new LineDrawListener(canvas, canvasPane); 
    btn.setOnAction(listener); 

    VBox root = new VBox(btn, canvasPane); 

    Scene scene = new Scene(root); 

    primaryStage.setScene(scene); 
    primaryStage.setResizable(false); 
    primaryStage.show(); 
} 
+0

非常感謝,非常樂於助人! – xn139

0

此行

canvasHolder.getChildren().addAll(l); 

嘗試在每次單擊時將相同的行l添加到canvasHolder

禁止多次將相同的組件添加到組件樹中。您應該在每次點擊時創建並添加新的Line

您同時定義了onMousePressedonMouseDragged處理程序自由拉伸模式,只有onMousePressed取代了直線模式。這導致,而不是純粹的直線模式,一些模式組合被激活。要解決這個問題,您應該刪除onMouseDragged處理程序,或者以與onMousePressed相同的方式重新定義它。

+0

Hi @ kgeorgiy,這是更喜歡它:canvasHolder.getChildren()。addAll(new Line(event.getX(),event.getY()));? – xn139

+0

我嘗試了你所說的,但它仍然允許免費抽籤。 – xn139

+0

補充說明 – kgeorgiy