-1

I created a simple paint program which allows the user to choose between 4 shapes(line,circle,rectangle,ellipse) , the user can change the width height and stroke width , he can save the design he makes , undo and redo , the user can also choose the stroke type (solid or dashed) ,I'm almost done with the program but I'm facing one problem , the line is getting displayed not in the way I want it to be displayed as the photo below :

Line

So the line here is of width 32 and height 32 , my line is getting printed in a different way.Is it correct the way I'm printing my line ?

NOTE : I'm using the line shape in the code to make the code small.

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);
    }
}
  • 2
    *"the line is getting displayed not in the way I want it to be displayed "*. What is the way you want it to be displayed? – James_D Sep 27 '21 at 14:09
  • I've shown a picture – Mohammed Hamdoon Sep 27 '21 at 14:25
  • @James_D I've included a picture – Mohammed Hamdoon Sep 27 '21 at 14:25
  • 1
    OK, if the picture is how you want it, then how is the current code displaying it? Please provide an actual [mre]: one we can copy and paste the code, compile it, and run it. The code you posted doesn't even compile. Get rid of all the irrelevant stuff, and complete it so it compiles and actually does something when it's executed. – James_D Sep 27 '21 at 14:27
  • @James_D sorry about that , I've just edited the code – Mohammed Hamdoon Sep 27 '21 at 14:44
  • So the issue is the size/shape of the dashes and the size of the gaps between them? – James_D Sep 27 '21 at 17:56
  • @James_D the issue is with , the rectangualr border around the line , and the way my line is getting printed , my line is getting printed from bottom to top , in other words m the starting of the line is the mouse pointer and it goes up , I want it to be the other way around , the mouse pointer as the starting point and the the line goes down – Mohammed Hamdoon Sep 27 '21 at 18:59

1 Answers1

2

Focusing on just drawing a line interactively, you need to at least do the following:

  1. Record the initial point at which the mouse was pressed and then

  2. Render the line when you know where the mouse was released:

     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());
     });
    

image

This works as shown above, but the problem then becomes how to draw the line while dragging—without damaging previous work. One solution is to add each new line to a List<Line> and render the accumulated lines with each update:

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());
    }
});

A more general solution, which illustrates undo() and redo(), is offered here.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045