JavaFX画布绘制

JavaFX画布绘制,java,javafx,Java,Javafx,我目前正在使用画布开发JavaFX绘图应用程序。在GraphicsContext的帮助下,我使用beginPath()和lineTo()方法绘制线条,但我无法找到实现橡皮擦的正确方法 现在我只使用clearRect()方法,但在像图像中那样快速拖动鼠标时会出现问题。 黑色=绘制,白色=橡皮擦 看看我的实现:) packagegui; 导入javafx.application.application; 导入javafx.application.Platform; 导入javafx.geometr

我目前正在使用画布开发JavaFX绘图应用程序。在GraphicsContext的帮助下,我使用beginPath()和lineTo()方法绘制线条,但我无法找到实现橡皮擦的正确方法

现在我只使用clearRect()方法,但在像图像中那样快速拖动鼠标时会出现问题。 黑色=绘制,白色=橡皮擦

看看我的实现:)

packagegui;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.geometry.Insets;
导入javafx.geometry.Orientation;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.canvas.canvas;
导入javafx.scene.canvas.GraphicsContext;
导入javafx.scene.control.*;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.HBox;
导入javafx.scene.paint.Color;
导入javafx.stage.stage;
公共类主扩展应用程序{
专用最终int mouseOffset=60;
私人舞台窗口;
私人帆布;
私有图形上下文gc;
@凌驾
公共无效开始(阶段primaryStage){
窗口=初级阶段;
window.setTitle(“由Michael Holley绘制的绘图板”);
window.setX(100);
窗口。setY(100);
window.setresizeable(false);
window.setOnCloseRequest(e->{
Platform.exit();
系统出口(0);
});
BorderPane布局=新建BorderPane();
/*选项窗格*/
HBox optionPane=新的HBox();
optionPane.setPrefHeight(60);
optionPane.setSpacing(10);
选项窗格。设置填充(新插图(10,10,10,10));
选项窗格。设置对齐(位置中心);
ColorPicker colorSelection=新的ColorPicker();
颜色选择。设置值(颜色。矢车菊蓝);
colorSelection.setOnAction(actionEvent->{
gc.setFill(colorSelection.getValue());
gc.setStroke(colorSelection.getValue());
});
optionPane.getChildren().add(颜色选择);
滑块大小滑块=新滑块();
尺寸滑块设置最小值(1);
尺寸滑块设定最大值(50);
sizeSlider.setValue(18);
optionPane.getChildren().add(sizeSlider);
TextField sizeSliderTF=新TextField();
sizeSliderTF.setEditable(false);
sizeSliderTF.setText(String.format(“%.0f”,sizeSlider.getValue());
sizeSliderTF.setPrefWidth(30);
尺寸滑块设置对齐(位置中心);
sizeSlider.valueProperty().addListener((ObservalEvalue、oldNumber、newNumber)->{
sizeSlider.setValue(newNumber.intValue());
sizeSliderTF.setText(String.format(“%.0f”,sizeSlider.getValue());
gc.setLineWidth(sizeSlider.getValue());
});
optionPane.getChildren().add(sizeSliderTF);
分离器选项窗格分离器_1=新分离器();
optionPaneSeparator_1.设置方向(方向.垂直);
optionPane.getChildren().add(optionPaneSeparator_1);
最终ToggleGroup=新ToggleGroup();
RadioButton drawButton=新RadioButton(“Draw”);
drawButton.setToggleGroup(组);
drawButton.setSelected(真);
RadioButton擦除按钮=新的RadioButton(“擦除”);
擦除按钮。设置切换组(组);
optionPane.getChildren().addAll(drawButton、橡皮擦按钮);
分离器选项窗格分离器2=新分离器();
选项窗格分离器2.设置方向(方向.垂直);
optionPane.getChildren().add(optionPaneSeparator_2);
按钮清除按钮=新按钮(“清除”);
clearButton.setOnAction(actionEvent->gc.clearRect(0,0,canvas.getWidth(),canvas.getHeight());
optionPane.getChildren().add(clearButton);
按钮填充按钮=新按钮(“填充”);
fillButton.setOnAction(actionEvent->gc.fillRect(0,0,canvas.getWidth(),canvas.getHeight());
optionPane.getChildren().add(fillButton);
布局。机顶盒(选项窗格);
/*帆布*/
画布=新画布(800740);
gc=canvas.getGraphicsContext2D();
gc.setStroke(colorSelection.getValue());
gc.setFill(colorSelection.getValue());
gc.setLineWidth(sizeSlider.getValue());
canvas.setOnMousePressed(mouseEvent->{
if(drawButton.isSelected()&&!eraseButton.isSelected()){
gc.beginPath();
gc.lineTo(mouseEvent.getSceneX(),mouseEvent.getSceneY()-mouseOffset);
gc.stroke();
}如果(!drawButton.isSelected()&&eraseButton.isSelected()),则为else{
double currentSize=sizeSlider.getValue();
gc.clearRect(mouseEvent.getSceneX()-currentSize/2,mouseEvent.getSceneY()-currentSize/2-mouseOffset,currentSize,currentSize);
}
});
canvas.setonmousedrable(mouseEvent->{
if(drawButton.isSelected()&&!eraseButton.isSelected()){
gc.lineTo(mouseEvent.getSceneX(),mouseEvent.getSceneY()-mouseOffset);
gc.stroke();
}如果(!drawButton.isSelected()&&eraseButton.isSelected()),则为else{
double currentSize=sizeSlider.getValue();
gc.clearRect(mouseEvent.getSceneX()-currentSize/2,mouseEvent.getSceneY()-currentSize/2-mouseOffset,currentSize,currentSize);
}
});
布局。设置中心(画布);
场景=新场景(布局,800800);
scene.getStylesheets().add(“GUI/optionsStyleing.css”);
window.setScene(场景);
window.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}
附加评论:
是的,我已经考虑过只使用底色/底色在其上进行绘制,但这不是我使用橡皮擦的理想目标。它被编码在我的(性能良好的)笔记本电脑上
import javafx.geometry.Point2D;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Rotate;

// ...

private Point2D lastErasePoint;

// ...

    canvas.setOnMousePressed(mouseEvent -> {
        if (drawButton.isSelected() && !eraseButton.isSelected()) {
            gc.beginPath();
            gc.lineTo(mouseEvent.getSceneX(), mouseEvent.getSceneY() - mouseOffset);
            gc.stroke();
        } else if (!drawButton.isSelected() && eraseButton.isSelected()) {
            lastErasePoint = new Point2D(
                mouseEvent.getSceneX(), mouseEvent.getSceneY() - mouseOffset);
        }
    });

    canvas.setOnMouseDragged(mouseEvent -> {
        if (drawButton.isSelected() && !eraseButton.isSelected()) {
            gc.lineTo(mouseEvent.getSceneX(), mouseEvent.getSceneY() - mouseOffset);
            gc.stroke();
        } else if (!drawButton.isSelected() && eraseButton.isSelected()) {
            Point2D location = new Point2D(
                mouseEvent.getSceneX(), mouseEvent.getSceneY() - mouseOffset);

            Point2D diff = location.subtract(lastErasePoint);
            double angle = Math.toDegrees(
                Math.atan2(diff.getY(), diff.getX()));
            double width = gc.getLineWidth();

            gc.save();
            gc.setTransform(new Affine(new Rotate(
                angle, lastErasePoint.getX(), lastErasePoint.getY())));
            gc.clearRect(
                lastErasePoint.getX() - width / 2,
                lastErasePoint.getY() - width / 2,
                lastErasePoint.distance(location) + width, width);
            gc.restore();

            lastErasePoint = location;
        }
    });