绘画程序JavaFX中的线条绘画

Line painting in painting program JavaFX

我创建了一个简单的绘画程序,允许用户在 4 种形状(线、圆、矩形、椭圆)之间进行选择,用户可以更改宽度高度和笔划宽度,他可以保存他所做的设计,撤消和重做,用户还可以选择笔划类型(实线或虚线),我几乎完成了该程序,但我遇到了一个问题,线条的显示方式与我希望的显示方式不同下面的照片:

所以这里的线条宽度为 32,高度为 32,我的线条以不同的方式打印 way.Is 它正确地打印了我的线条?

注意:我在代码中使用线形来使代码变小。

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class paintLine extends Application {

@Override
public void start(Stage primaryStage) {

    Image image1 = new
            
Image("C:\Users\Mhamd\Desktop\laol\src\resources\Daco_70400.png", 
100, 100, false, false);
    ImageView view1 = new ImageView(image1);
    view1.setFitHeight(40);
    view1.setPreserveRatio(true);
    ToggleButton linebtn = new ToggleButton();
    linebtn.setGraphic(view1);
    ToggleButton[] toolsArr = {linebtn};

    ToggleGroup tools = new ToggleGroup();

    for (ToggleButton tool : toolsArr) {
        tool.setMinWidth(50);
        tool.setToggleGroup(tools);
        tool.setCursor(Cursor.HAND);
    }
    ColorPicker cpLine = new ColorPicker(Color.BLACK);
    ColorPicker cpFill = new ColorPicker(Color.TRANSPARENT);

    TextField textWidth = new TextField("32");
    TextField textHeight = new TextField("32");
    TextField contouring = new TextField("2");
    Label line_color = new Label("Line Color");
    Label fill_color = new Label("Fill Color");
    Label line_width = new Label("3.0");
    Label imgWidth = new Label("Width");
    Label imgHeight = new Label("Height");
    String week_days[] =
            {"Solid", "Dotted"};
    ChoiceBox choiceBox = new ChoiceBox(FXCollections
            .observableArrayList(week_days));
    VBox btns = new VBox(10);
    btns.getChildren().addAll(linebtn, imgWidth, textWidth, imgHeight, 
textHeight, line_color, cpLine,
            fill_color, cpFill, line_width, contouring, choiceBox);
    btns.setPadding(new Insets(5));
    btns.setStyle("-fx-background-color: #999");
    btns.setPrefWidth(100);
    Canvas canvas = new Canvas(1080, 790);
    GraphicsContext gc;
    gc = canvas.getGraphicsContext2D();
    gc.setLineWidth(1);
    Line line = new Line();
    canvas.setOnMouseClicked(e -> {
        if (linebtn.isSelected()) {
//                double widthSize = 
 Double.parseDouble(textWidth.getText());
//                double heightSize = 
Double.parseDouble(textHeight.getText());
            double strokeWidth = 
Double.parseDouble(contouring.getText());
//                gc.setLineWidth(strokeWidth);
            gc.setStroke(cpLine.getValue());
            if (choiceBox.getSelectionModel().isSelected(0)) {
                gc.setLineWidth(strokeWidth);
            } else if (choiceBox.getSelectionModel().isSelected(1)) {
                gc.setLineWidth(strokeWidth);
                gc.setLineDashes(10);
            }
            gc.setFill(cpFill.getValue());
            line.setStartX(e.getX());
            line.setStartY(e.getY());
            line.setEndX(e.getX() / 2);
            line.setEndY(e.getY() / 2);
            gc.strokeLine(line.getStartX(), line.getStartY(), 
line.getEndX(), line.getEndY());
        }
    });
    BorderPane pane = new BorderPane();
    pane.setRight(btns);
    pane.setCenter(canvas);

    Scene scene = new Scene(pane, 1200, 800);

    primaryStage.setTitle("Paint");
    primaryStage.setScene(scene);
    primaryStage.show();
}
    public static void main(String[] args) {
        launch(args);
    }
}

专注于只是交互式画线,您需要至少执行以下操作:

  1. 记录鼠标按下的起始点,然后

  2. 当你知道鼠标放在哪里时渲染线条:

     private double startX;
     private double startY;
     …
     canvas.setOnMousePressed(e -> {
         startX = e.getX();
         startY = e.getY();
     });
     canvas.setOnMouseReleased(e -> {
         gc.strokeLine(startX, startY, e.getX(), e.getY());
     });
    

如上所示,但 变成了如何在 拖动时画线,而不会损坏之前的工作。一种解决方案是将每个新行添加到 List<Line> 并在每次更新时呈现累积的行:

private final List<Line> lines = new ArrayList<>();
…
canvas.setOnMouseReleased(e -> {
    lines.add(new Line(startX, startY, e.getX(), e.getY()));
});
canvas.setOnMouseDragged(e -> {
    if (lineButton.isSelected()) {
        …
        gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
        lines.forEach(l -> {
            gc.strokeLine(l.getStartX(), l.getStartY(), l.getEndX(), l.getEndY());
        });
        gc.strokeLine(startX, startY, e.getX(), e.getY());
    }
});

提供了一个更通用的解决方案,它说明了 undo()redo()