2016-11-05 1 views
0

Я создаю небольшую программу рисования с использованием JavaFX. Я успешно реализовал бесплатный рисунок на холсте. Тем не менее, я также хочу, чтобы иметь возможность рисовать прямые линии от точки, на которую я нажимаю, когда моя мышь нажата. Я создаю строку заранее, однако я не могу переключить контекст, чтобы рисовать прямые линии вместо свободного рисования.Попытка переключить контекст GraphicsContext в JavaFX

На данный момент, если бы я нажал кнопку «Прямая линия», она нарисовала одну прямую линию, а затем по умолчанию вернулась к свободному рисунку, бросая много ошибок. Не могли бы вы помочь?

Вот мой код для свободного рисования:

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

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

(где дс является 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 на каждый клик.

определяется как onMousePressed и onMouseDragged обработчиков для режима свободного рисования и заменяет только onMousePressed для прямого режима. Это приводит к тому, что вместо чистого режима прямой линии активируется некоторая комбинация режимов. Чтобы исправить это, вы должны либо удалить обработчик onMouseDragged, либо переопределить его так же, как onMousePressed.

+0

Привет @kgeorgiy, это больше похоже на это: canvasHolder.getChildren(). AddAll (новая строка (event.getX(), event.getY())) ;? – xn139

+0

Я пробовал то, что вы сказали, но он все еще позволяет провести бесплатную ничью. – xn139

+0

Добавлено сглаживание – kgeorgiy

Смежные вопросы