diff --git a/lab-03/Paint/pom.xml b/lab-03/Paint/pom.xml new file mode 100644 index 0000000..acb73dd --- /dev/null +++ b/lab-03/Paint/pom.xml @@ -0,0 +1,134 @@ + + + 4.0.0 + + com.example + Paint + 1.0-SNAPSHOT + Paint + + + UTF-8 +5.9.2 + + + + org.openjfx + javafx-controls + 21-ea+24 + + + org.openjfx + javafx-fxml + 21-ea+24 + + + org.openjfx + javafx-web + 21-ea+24 + + org.openjfx + javafx-media + 21-ea+24 + + org.controlsfx + controlsfx + 11.1.2 + + com.dlsc.formsfx + formsfx-core + 11.6.0 + + + org.openjfx + * + + + + net.synedra + validatorfx + 0.4.0 + + + org.openjfx + * + + + + org.kordamp.ikonli + ikonli-javafx + 12.3.1 + + org.kordamp.bootstrapfx + bootstrapfx-core + 0.4.0 + + eu.hansolo + tilesfx + 17.1.17 + + + org.openjfx + * + + + + com.github.almasb + fxgl + 17.2 + + + org.openjfx + * + + + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 21 + 21 + + + + org.openjfx + javafx-maven-plugin + 0.0.8 + + + + default-cli + + com.example.paint/by.BelArtem.paint.HelloApplication + app + app + app + true + true + true + + + + + + + \ No newline at end of file diff --git a/lab-03/Paint/src/main/java/by/BelArtem/paint/Paint.java b/lab-03/Paint/src/main/java/by/BelArtem/paint/Paint.java new file mode 100644 index 0000000..d580605 --- /dev/null +++ b/lab-03/Paint/src/main/java/by/BelArtem/paint/Paint.java @@ -0,0 +1,358 @@ +package by.BelArtem.paint; + +import javafx.application.Application; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.embed.swing.SwingFXUtils; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Insets; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.ColorPicker; +import javafx.scene.control.ComboBox; +import javafx.scene.control.Slider; +import javafx.scene.image.ImageView; +import javafx.scene.image.WritableImage; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.*; +import javafx.scene.control.Label; +import javafx.scene.paint.Color; +import javafx.scene.shape.*; +import javafx.scene.shape.Rectangle; +import javafx.stage.FileChooser; +import javafx.stage.Stage; +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; +import java.io.File; + +public class Paint extends Application { + + private HBox root; + private VBox vBox; + private Label comboboxLabel; + private Label sliderLabel; + private Label colorLabel; + private ComboBox figures; + private Slider sizeSlider; + private ColorPicker colorPicker; + private Button clearButton; + private Button saveButton; + private Button loadButton; + private Pane drawingPane; + private FileChooser fileChooser; + private String curFigure; + private int curSize; + private Color curColor; + private Point point; + + + public static void main(String[] args) { + Application.launch(args); + } + + @Override + public void start(Stage stage) throws Exception { + this.setVboxLayout(); + + root = new HBox(); + Scene scene = new Scene(root, 1500, 900); + root.getChildren().add(vBox); + + this.setDrawingPane(); + HBox.setMargin(drawingPane, new Insets(0,0,0,10)); + root.getChildren().add(drawingPane); + + this.setToolBarActions(); + this.setDrawingActions(); + + fileChooser = new FileChooser(); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("png files (*.png)", "*.png")); + point = new Point(); + + stage.setScene(scene); + stage.setTitle("Paint"); + stage.setResizable(false); + stage.show(); + } + + private void setDrawingPane() { + drawingPane = new Pane(); + drawingPane.setMinWidth(1320); + drawingPane.setMinHeight(900); + drawingPane.setBackground(new Background(new BackgroundFill(Color.rgb(200,200,200), CornerRadii.EMPTY, Insets.EMPTY))); + } + + private void setVboxLayout() { + this.vBox = new VBox(); + + comboboxLabel = new Label("Choose figure to draw:"); + + VBox.setMargin(comboboxLabel, new Insets(200,0,0,10)); + vBox.getChildren().add(comboboxLabel); + + figures = new ComboBox<>(); + figures.getItems().addAll("Pen", "Line", "Rectangle", "Circle"); + figures.setValue("Pen"); + this.curFigure = figures.getValue(); + + VBox.setMargin(figures, new Insets(10,0,0,10)); + vBox.getChildren().add(figures); + + sliderLabel = new Label("Choose the size:"); + + VBox.setMargin(sliderLabel, new Insets(50,0,0,10)); + vBox.getChildren().add(sliderLabel); + + sizeSlider = new Slider(1,10,1); + sizeSlider.setShowTickMarks(true); + sizeSlider.setShowTickLabels(true); + sizeSlider.setBlockIncrement(1); + sizeSlider.setMajorTickUnit(1); + sizeSlider.setMinorTickCount(0); + sizeSlider.setSnapToTicks(true); + sizeSlider.setValue(3); + this.curSize = (int)sizeSlider.getValue(); + + VBox.setMargin(sizeSlider, new Insets(10,0,0,10)); + vBox.getChildren().add(sizeSlider); + + colorLabel = new Label("Choose the color:"); + + VBox.setMargin(colorLabel, new Insets(50,0,0,10)); + vBox.getChildren().add(colorLabel); + + colorPicker = new ColorPicker(); + colorPicker.setValue(Color.BLACK); + this.curColor = colorPicker.getValue(); + + VBox.setMargin(colorPicker, new Insets(10,0,0,10)); + vBox.getChildren().add(colorPicker); + + clearButton = new Button("Clear all"); + clearButton.setPrefSize(90,20); + VBox.setMargin(clearButton, new Insets(40,0,0,10)); + vBox.getChildren().add(clearButton); + + saveButton = new Button("Save"); + saveButton.setPrefSize(90,20); + VBox.setMargin(saveButton, new Insets(50,0,0,10)); + vBox.getChildren().add(saveButton); + + loadButton = new Button("Load"); + loadButton.setPrefSize(90,20); + VBox.setMargin(loadButton, new Insets(20,0,0,10)); + vBox.getChildren().add(loadButton); + + vBox.setMinWidth(180); + } + + private void setToolBarActions() { + figures.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent actionEvent) { + curFigure = figures.getValue(); + } + }); + + sizeSlider.valueProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observableValue, Number number, Number t1) { + curSize = (int)sizeSlider.getValue(); + } + }); + + colorPicker.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent actionEvent) { + curColor = colorPicker.getValue(); + } + }); + + clearButton.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent actionEvent) { + drawingPane.getChildren().clear(); + } + }); + + saveButton.setOnAction(new EventHandler() { + + @Override + public void handle(ActionEvent actionEvent) { + File file = fileChooser.showSaveDialog(null); + if (file != null) { + try{ + WritableImage writableImage = new WritableImage((int)drawingPane.getWidth(), (int)drawingPane.getHeight()); + drawingPane.snapshot(null, writableImage); + RenderedImage renderedImage = SwingFXUtils.fromFXImage(writableImage, null); + ImageIO.write(renderedImage, "png", file); + } catch (Exception e){ + System.out.println("An error occurred while selecting file"); + e.printStackTrace(); + } + } + } + }); + + loadButton.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent actionEvent) { + File file = fileChooser.showOpenDialog(null); + if (file != null) { + try{ + BufferedImage bufferedImage = ImageIO.read(file); + WritableImage writableImage = SwingFXUtils.toFXImage(bufferedImage, null); + ImageView imageView = new ImageView(writableImage); + + drawingPane.getChildren().clear(); + drawingPane.getChildren().add(imageView); + } catch (Exception e) { + System.out.println("An error occurred while selecting file"); + e.printStackTrace(); + } + + } + } + }); + } + + private void setDrawingActions() { + drawingPane.setOnMousePressed(mouseEvent -> { + double x = mouseEvent.getX(); + double y = mouseEvent.getY(); + if (x < 0 || y < 0){ + return; + } + switch (curFigure){ + case "Pen": + createPen(x, y); + break; + case "Line": + createLine(x, y); + break; + case "Rectangle": + createRectangle(x, y); + break; + case "Circle": + createCircle(x, y); + break; + default: + System.out.println("Something went wrong"); + } + }); + + drawingPane.setOnMouseDragged(new EventHandler() { + @Override + public void handle(MouseEvent mouseEvent) { + double x = mouseEvent.getX(); + double y = mouseEvent.getY(); + if (x < 0 || y < 0){ + return; + } + switch (curFigure){ + case "Pen": + drawPen(x,y); + break; + case "Line": + drawLine(x,y); + break; + case "Rectangle": + drawRectangle(x,y); + break; + case "Circle": + drawCircle(x, y); + break; + default: + System.out.println("Smth went wrong"); + } + } + }); + } + + private void createPen(double x, double y) { + point.setLocation(x,y); + } + + private void drawPen(double x, double y) { + Line line = new Line(); + line.setStartX(point.getX()); + line.setStartY(point.getY()); + line.setEndX(x); + line.setEndY(y); + point.setLocation(x,y); + line.setStroke(curColor); + line.setStrokeWidth(curSize); + line.setStrokeLineCap(StrokeLineCap.ROUND); + + drawingPane.getChildren().add(line); + } + + private void createLine(double x, double y) { + Line line = new Line(x,y,x,y); + line.setStroke(curColor); + line.setStrokeWidth(curSize); + line.setStrokeLineCap(StrokeLineCap.ROUND); + + drawingPane.getChildren().add(line); + } + + private void drawLine(double x, double y) { + Line line = (Line)drawingPane.getChildren().getLast(); + line.setEndX(x); + line.setEndY(y); + } + private void createRectangle(double x, double y) { + Rectangle rect = new Rectangle(); + rect.setFill(Color.TRANSPARENT); + rect.setStroke(curColor); + rect.setStrokeWidth(curSize); + drawingPane.getChildren().add(rect); + rect.setX(x); + rect.setY(y); + point.setLocation(x,y); + } + + private void drawRectangle(double x, double y) { + Rectangle rectangle = (Rectangle) drawingPane.getChildren().getLast(); + double px = point.getX(); + double py = point.getY(); + if (x >= point.getX() && y >= point.getY()) { + rectangle.setWidth(x - px); + rectangle.setHeight(y - py); + return; + } + double xVert = Math.min(px, x); + double yVert = Math.min(py, y); + + rectangle.setHeight(Math.abs(y - py)); + rectangle.setWidth(Math.abs(x - px)); + rectangle.setX(xVert); + rectangle.setY(yVert); + } + + private void createCircle(double x, double y) { + Circle circle = new Circle(x, y ,0); + circle.setStroke(curColor); + circle.setStrokeWidth(curSize); + circle.setFill(Color.TRANSPARENT); + point.setLocation(x,y); + + drawingPane.getChildren().add(circle); + } + + private void drawCircle(double x, double y) { + Circle circle = (Circle) drawingPane.getChildren().getLast(); + double px = point.getX(); + double py = point.getY(); + double width = x - px; + double height = y - py; + double rad = Math.min(Math.abs(width), Math.abs(height)) / 2; + circle.setRadius(rad); + + circle.setCenterX(width < 0 ? px - rad : px + rad); + circle.setCenterY(height < 0 ? py - rad : py + rad); + } +}