From dcdfefaebe4d354262a36f4c8668d3ca36a6e831 Mon Sep 17 00:00:00 2001 From: aadeglmmy Date: Fri, 22 Dec 2023 19:35:20 +0300 Subject: [PATCH 1/3] Lab03 --- lab-03/README.md | 19 -- lab-03/by/aadeglmmy/paint/DrawingData.java | 42 ++++ lab-03/by/aadeglmmy/paint/LineData.java | 53 +++++ lab-03/by/aadeglmmy/paint/OvalData.java | 53 +++++ lab-03/by/aadeglmmy/paint/RectangleData.java | 53 +++++ lab-03/by/aadeglmmy/paint/SimplePaintApp.java | 216 ++++++++++++++++++ 6 files changed, 417 insertions(+), 19 deletions(-) delete mode 100644 lab-03/README.md create mode 100644 lab-03/by/aadeglmmy/paint/DrawingData.java create mode 100644 lab-03/by/aadeglmmy/paint/LineData.java create mode 100644 lab-03/by/aadeglmmy/paint/OvalData.java create mode 100644 lab-03/by/aadeglmmy/paint/RectangleData.java create mode 100644 lab-03/by/aadeglmmy/paint/SimplePaintApp.java diff --git a/lab-03/README.md b/lab-03/README.md deleted file mode 100644 index 746bed6..0000000 --- a/lab-03/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Paint -В данной задаче вам предстоит написать упрощенный Paint. - - - -# Порядок выполнения -- Создать фрейм с областью для рисования (мышь оставляет след). -- Реализовать смену цвета и размера пера. -- Добавить возможность рисовать круг и прямоугольник (в идеале как в paint, но можно и по точкам). -- Реализовать сохранение рисунка в файле и его последующее открытие (используйте механизм сериализации объектов). - ->Всю работу ведите в пакете `by.<ваш ник>.paint` - -# ★ JavaFx -Реализуйте приложения с помощью `JavaFx`. - -# Полезные ссылки -- Сохранение изображения — https://docs.oracle.com/javase/tutorial/2d/images/saveimage.html -- JavaFx — https://metanit.com/java/javafx/1.1.php diff --git a/lab-03/by/aadeglmmy/paint/DrawingData.java b/lab-03/by/aadeglmmy/paint/DrawingData.java new file mode 100644 index 0000000..6670993 --- /dev/null +++ b/lab-03/by/aadeglmmy/paint/DrawingData.java @@ -0,0 +1,42 @@ +package by.aadeglmmy.paint; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class DrawingData implements Serializable { + + private final List lines; + private final List ovals; + private final List rectangles; + + public DrawingData() { + lines = new ArrayList<>(); + ovals = new ArrayList<>(); + rectangles = new ArrayList<>(); + } + + public void addLine(LineData lineData) { + lines.add(lineData); + } + + public void addOval(OvalData ovalData) { + ovals.add(ovalData); + } + + public void addRectangle(RectangleData rectangleData) { + rectangles.add(rectangleData); + } + + public List getLines() { + return lines; + } + + public List getOvals() { + return ovals; + } + + public List getRectangles() { + return rectangles; + } +} diff --git a/lab-03/by/aadeglmmy/paint/LineData.java b/lab-03/by/aadeglmmy/paint/LineData.java new file mode 100644 index 0000000..eb83a29 --- /dev/null +++ b/lab-03/by/aadeglmmy/paint/LineData.java @@ -0,0 +1,53 @@ +package by.aadeglmmy.paint; + +import java.io.Serializable; +import javafx.scene.paint.Color; + +public class LineData implements Serializable { + + private final double startX; + private final double startY; + private final double endX; + private final double endY; + private final int colorRed; + private final int colorGreen; + private final int colorBlue; + private final double width; + + public LineData(double startX, double startY, double endX, double endY, Color color, double width, + DrawingData drawing) { + this.startX = startX; + this.startY = startY; + this.endX = endX; + this.endY = endY; + this.colorRed = (int) (color.getRed() * 255); + this.colorGreen = (int) (color.getGreen() * 255); + this.colorBlue = (int) (color.getBlue() * 255); + this.width = width; + drawing.addLine(this); + } + + public double getStartX() { + return startX; + } + + public double getStartY() { + return startY; + } + + public double getEndX() { + return endX; + } + + public double getEndY() { + return endY; + } + + public Color getColor() { + return Color.rgb(colorRed, colorGreen, colorBlue); + } + + public double getWidth() { + return width; + } +} diff --git a/lab-03/by/aadeglmmy/paint/OvalData.java b/lab-03/by/aadeglmmy/paint/OvalData.java new file mode 100644 index 0000000..a6265c6 --- /dev/null +++ b/lab-03/by/aadeglmmy/paint/OvalData.java @@ -0,0 +1,53 @@ +package by.aadeglmmy.paint; + +import java.io.Serializable; +import javafx.scene.paint.Color; + +public class OvalData implements Serializable { + + private final double x; + private final double y; + private final double width; + private final double height; + private final int colorRed; + private final int colorGreen; + private final int colorBlue; + private final double brushWidth; + + public OvalData(double x, double y, double width, double height, Color color, double brushWidth, + DrawingData drawing) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.colorRed = (int) (color.getRed() * 255); + this.colorGreen = (int) (color.getGreen() * 255); + this.colorBlue = (int) (color.getBlue() * 255); + this.brushWidth = brushWidth; + drawing.addOval(this); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } + + public Color getColor() { + return Color.rgb(colorRed, colorGreen, colorBlue); + } + + public double getBrushWidth() { + return brushWidth; + } +} diff --git a/lab-03/by/aadeglmmy/paint/RectangleData.java b/lab-03/by/aadeglmmy/paint/RectangleData.java new file mode 100644 index 0000000..bf3abea --- /dev/null +++ b/lab-03/by/aadeglmmy/paint/RectangleData.java @@ -0,0 +1,53 @@ +package by.aadeglmmy.paint; + +import java.io.Serializable; +import javafx.scene.paint.Color; + +public class RectangleData implements Serializable { + + private final double x; + private final double y; + private final double width; + private final double height; + private final int colorRed; + private final int colorGreen; + private final int colorBlue; + private final double brushWidth; + + public RectangleData(double x, double y, double width, double height, Color color, double brushWidth, + DrawingData drawing) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.colorRed = (int) (color.getRed() * 255); + this.colorGreen = (int) (color.getGreen() * 255); + this.colorBlue = (int) (color.getBlue() * 255); + this.brushWidth = brushWidth; + drawing.addRectangle(this); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } + + public Color getColor() { + return Color.rgb(colorRed, colorGreen, colorBlue); + } + + public double getBrushWidth() { + return brushWidth; + } +} diff --git a/lab-03/by/aadeglmmy/paint/SimplePaintApp.java b/lab-03/by/aadeglmmy/paint/SimplePaintApp.java new file mode 100644 index 0000000..a7d31d0 --- /dev/null +++ b/lab-03/by/aadeglmmy/paint/SimplePaintApp.java @@ -0,0 +1,216 @@ +package by.aadeglmmy.paint; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import javafx.application.Application; +import javafx.geometry.Insets; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.Button; +import javafx.scene.control.ColorPicker; +import javafx.scene.control.ComboBox; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.stage.FileChooser; +import javafx.stage.Stage; + +public class SimplePaintApp extends Application { + + Canvas canvas = new Canvas(800, 800); + DrawingData drawing = new DrawingData(); + private GraphicsContext graphicsContext; + private ColorPicker colorPicker; + private ComboBox brushSizeComboBox; + private double startX, startY; + private boolean ovalMode = false; + private boolean rectangleMode = false; + private boolean brushMode = true; + private double previousX, previousY; + + public SimplePaintApp() { + } + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + Rectangle canvasBorder = new Rectangle(800, 800); + canvasBorder.setStroke(Color.BLACK); + canvasBorder.setFill(Color.TRANSPARENT); + graphicsContext = canvas.getGraphicsContext2D(); + graphicsContext.setStroke(Color.BLACK); + graphicsContext.setLineWidth(1.0); + + colorPicker = new ColorPicker(); + colorPicker.setValue(Color.BLACK); + colorPicker.setOnAction(e -> graphicsContext.setStroke(colorPicker.getValue())); + + brushSizeComboBox = new ComboBox<>(); + brushSizeComboBox.getItems().addAll(1, 3, 5, 8); + brushSizeComboBox.setValue(1); + brushSizeComboBox.setOnAction(e -> graphicsContext.setLineWidth(brushSizeComboBox.getValue())); + + Button brushButton = new Button("Brush"); + Button ovalButton = new Button("Oval"); + Button rectangleButton = new Button("Rectangle"); + + brushButton.setOnAction(e -> { + ovalMode = false; + rectangleMode = false; + brushMode = true; + }); + + ovalButton.setOnAction(e -> { + ovalMode = true; + rectangleMode = false; + brushMode = false; + }); + + rectangleButton.setOnAction(e -> { + ovalMode = false; + rectangleMode = true; + brushMode = false; + }); + + canvas.setOnMousePressed(e -> { + startX = e.getX(); + startY = e.getY(); + previousX = startX; + previousY = startY; + }); + + canvas.setOnMouseDragged(e -> { + if (brushMode) { + double x = e.getX(); + double y = e.getY(); + new LineData(previousX, previousY, x, y, colorPicker.getValue(), + brushSizeComboBox.getValue(), drawing); + graphicsContext.strokeLine(previousX, previousY, x, y); + previousX = x; + previousY = y; + } + }); + + canvas.setOnMouseReleased(e -> { + double endX = e.getX(); + double endY = e.getY(); + + double x = Math.min(startX, endX); + double y = Math.min(startY, endY); + double width = Math.abs(endX - startX); + double height = Math.abs(endY - startY); + + if (e.isShiftDown()) { + double minLength = Math.min(width, height); + width = minLength; + height = minLength; + } + + if (ovalMode) { + new OvalData(x, y, width, height, colorPicker.getValue(), brushSizeComboBox.getValue(), + drawing); + graphicsContext.strokeOval(x, y, width, height); + } else if (rectangleMode) { + new RectangleData(x, y, width, height, colorPicker.getValue(), brushSizeComboBox.getValue(), + drawing); + graphicsContext.strokeRect(x, y, width, height); + } + }); + + Button saveButton = new Button("Save"); + Button openButton = new Button("Open"); + + saveButton.setOnAction(e -> { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Save the drawing"); + File file = fileChooser.showSaveDialog(primaryStage); + if (file != null) { + saveDrawing(file.getAbsolutePath()); + } + }); + + openButton.setOnAction(e -> { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Open the drawing"); + File file = fileChooser.showOpenDialog(primaryStage); + if (file != null) { + openDrawing(file.getAbsolutePath()); + } + }); + + HBox buttonsBox = new HBox(brushButton, ovalButton, rectangleButton, saveButton, openButton); + buttonsBox.setSpacing(10); + buttonsBox.setPadding(new Insets(10)); + + HBox colorAndSizeBox = new HBox(colorPicker, brushSizeComboBox); + colorAndSizeBox.setSpacing(10); + colorAndSizeBox.setPadding(new Insets(10)); + + Pane canvasPane = new StackPane(); + canvasPane.getChildren().addAll(canvasBorder, canvas); + + BorderPane root = new BorderPane(); + root.setTop(colorAndSizeBox); + root.setCenter(canvasPane); + root.setLeft(buttonsBox); + + Scene scene = new Scene(root, 1600, 900); + + primaryStage.setTitle("Simple Paint"); + primaryStage.setScene(scene); + primaryStage.show(); + } + + public void saveDrawing(String filename) { + try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename))) { + outputStream.writeObject(drawing); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void openDrawing(String filename) { + try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(filename))) { + DrawingData drawingData = (DrawingData) inputStream.readObject(); + + graphicsContext.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); + drawing = drawingData; + + for (LineData line : drawingData.getLines()) { + graphicsContext.setStroke(line.getColor()); + graphicsContext.setLineWidth(line.getWidth()); + graphicsContext.strokeLine(line.getStartX(), line.getStartY(), line.getEndX(), + line.getEndY()); + } + + for (OvalData oval : drawingData.getOvals()) { + graphicsContext.setStroke(oval.getColor()); + graphicsContext.setLineWidth(oval.getBrushWidth()); + graphicsContext.strokeOval(oval.getX(), oval.getY(), oval.getWidth(), oval.getHeight()); + } + + for (RectangleData rectangle : drawingData.getRectangles()) { + graphicsContext.setStroke(rectangle.getColor()); + graphicsContext.setLineWidth(rectangle.getBrushWidth()); + graphicsContext.strokeRect(rectangle.getX(), rectangle.getY(), rectangle.getWidth(), + rectangle.getHeight()); + } + + graphicsContext.setStroke(colorPicker.getValue()); + graphicsContext.setLineWidth(brushSizeComboBox.getValue()); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} From 07c1548cd9093a2788ca543af4dad78a253e42b7 Mon Sep 17 00:00:00 2001 From: aadeglmmy Date: Sat, 23 Dec 2023 15:54:49 +0300 Subject: [PATCH 2/3] Added pom.xml --- lab-03/by/aadeglmmy/paint/pom.xml | 149 ++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 lab-03/by/aadeglmmy/paint/pom.xml diff --git a/lab-03/by/aadeglmmy/paint/pom.xml b/lab-03/by/aadeglmmy/paint/pom.xml new file mode 100644 index 0000000..a777ba7 --- /dev/null +++ b/lab-03/by/aadeglmmy/paint/pom.xml @@ -0,0 +1,149 @@ + + + 4.0.0 + + org.example + demo + 1.0-SNAPSHOT + demo + + + UTF-8 + 5.10.0 + + + + + org.openjfx + javafx-controls + 21 + + + org.openjfx + javafx-fxml + 21 + + + org.openjfx + javafx-web + 21 + + + org.openjfx + javafx-swing + 21 + + + org.openjfx + javafx-media + 21 + + + 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 + 11.48 + + + org.openjfx + * + + + + + com.github.almasb + fxgl + 17.3 + + + 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 + + org.example.demo/by.aadeglmmy.paint.demo.HelloApplication + app + app + app + true + true + true + + + + + + + \ No newline at end of file From 91bfc15f2f6b44997a6dae72a8bb9288fa90629d Mon Sep 17 00:00:00 2001 From: aadeglmmy Date: Sat, 23 Dec 2023 19:36:40 +0300 Subject: [PATCH 3/3] Added extension filter --- lab-03/by/aadeglmmy/paint/SimplePaintApp.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lab-03/by/aadeglmmy/paint/SimplePaintApp.java b/lab-03/by/aadeglmmy/paint/SimplePaintApp.java index a7d31d0..336a098 100644 --- a/lab-03/by/aadeglmmy/paint/SimplePaintApp.java +++ b/lab-03/by/aadeglmmy/paint/SimplePaintApp.java @@ -21,6 +21,7 @@ import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.FileChooser; +import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Stage; public class SimplePaintApp extends Application { @@ -134,6 +135,10 @@ public void start(Stage primaryStage) { saveButton.setOnAction(e -> { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Save the drawing"); + + ExtensionFilter filter = new ExtensionFilter("Paint Files (*.paint)", "*.paint"); + fileChooser.getExtensionFilters().add(filter); + File file = fileChooser.showSaveDialog(primaryStage); if (file != null) { saveDrawing(file.getAbsolutePath()); @@ -143,6 +148,10 @@ public void start(Stage primaryStage) { openButton.setOnAction(e -> { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Open the drawing"); + + ExtensionFilter filter = new ExtensionFilter("Paint Files (*.paint)", "*.paint"); + fileChooser.getExtensionFilters().add(filter); + File file = fileChooser.showOpenDialog(primaryStage); if (file != null) { openDrawing(file.getAbsolutePath());