feat: début environnement graphique, dessin fonctionnel, sauvegarde et chargement temporaire possible

This commit is contained in:
Emi Boucly 2025-03-17 11:14:27 +01:00
parent 8af801e4fd
commit 70e583a380
6 changed files with 195 additions and 19 deletions

View file

@ -36,7 +36,13 @@
<artifactId>junit-jupiter-engine</artifactId> <artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version> <version>${junit.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependencies> </dependency>
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>11.2.1</version>
</dependency>
</dependencies>
<build> <build>
<plugins> <plugins>

View file

@ -12,7 +12,7 @@ public class HelloApplication extends Application {
public void start(Stage stage) throws IOException { public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml")); FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240); Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!"); stage.setTitle("PixelWriter");
stage.setScene(scene); stage.setScene(scene);
stage.show(); stage.show();
} }

View file

@ -1,14 +1,100 @@
package fr.emiko.graphicalapp; package fr.emiko.graphicalapp;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.MenuItem;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import fr.emiko.graphicsElement.Stroke;
public class HelloController { import java.awt.*;
@FXML import java.net.URL;
private Label welcomeText; import java.util.ResourceBundle;
import java.util.Vector;
@FXML public class HelloController implements Initializable {
protected void onHelloButtonClick() { public Canvas drawingCanvas;
welcomeText.setText("Welcome to JavaFX Application!"); public MenuItem saveButton;
public MenuItem loadButton;
public MenuItem newCanvasButton;
private double posX = 0;
private double posY = 0;
private Vector<Stroke> strokes = new Vector<>();
private Vector<Stroke> lastSaved = new Vector<>();
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
drawingCanvas.setOnMouseDragged(this::printLine);
drawingCanvas.setOnMouseClicked(this::resetPos);
saveButton.setOnAction(this::onActionSave);
loadButton.setOnAction(this::onActionLoad);
newCanvasButton.setOnAction(this::onActionCreateCanvas);
} }
private void onActionCreateCanvas(ActionEvent actionEvent) {
}
private void onActionLoad(ActionEvent actionEvent) {
// drawingCanvas.getGraphicsContext2D().drawImage(lastSaved, 0, 0);
GraphicsContext gc = drawingCanvas.getGraphicsContext2D();
gc.clearRect(0, 0, drawingCanvas.getWidth(), drawingCanvas.getHeight());
for (Stroke stroke : lastSaved) {
stroke.draw(gc);
}
strokes = (Vector<Stroke>) lastSaved.clone();
}
private void onActionSave(ActionEvent actionEvent) {
GraphicsContext gc = drawingCanvas.getGraphicsContext2D();
lastSaved = (Vector<Stroke>) strokes.clone();
}
private void resetPos(MouseEvent mouseEvent) {
posX = 0;
posY = 0;
}
private void printLine(MouseEvent mouseEvent) {
GraphicsContext gc = drawingCanvas.getGraphicsContext2D();
// gc.setFill(Color.BLACK);
// gc.setStroke(Color.BLACK);
// gc.beginPath();
// if (posX == 0 || posY == 0) {
// posX = mouseEvent.getX();
// posY = mouseEvent.getY();
// }
// gc.moveTo(posX, posY);
// gc.lineTo(mouseEvent.getX(), mouseEvent.getY());
// gc.closePath();
// gc.stroke();
// posX = mouseEvent.getX();
// posY = mouseEvent.getY();
if (posX == 0 || posY == 0) {
posX = mouseEvent.getX();
posY = mouseEvent.getY();
}
Stroke stroke = new Stroke(posX, posY, mouseEvent.getX(), mouseEvent.getY());
strokes.add(stroke);
stroke.draw(gc);
posX = mouseEvent.getX();
posY = mouseEvent.getY();
System.out.println(stroke);
}
} }

View file

@ -0,0 +1,39 @@
package fr.emiko.graphicsElement;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.shape.Path;
import java.awt.*;
public class Stroke {
private final double fromX;
private final double fromY;
private final double toX;
private final double toY;
public Stroke (double fromX, double fromY, double toX, double toY) {
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
}
public void draw (GraphicsContext g) {
// g.setStroke(javafx.scene.paint.Color.BLACK);
// g.setLineWidth(1);
// g.beginPath();
// g.moveTo(fromX, fromY);
// g.lineTo(toX, toY);
// g.closePath();
// g.stroke();
// g.fill();
g.setFill(javafx.scene.paint.Color.BLACK);
g.fillOval(toX-5, toY-5, 10, 10);
}
@Override
public String toString () {
return "Stroke{fromX=%f, fromY=%f, toX=%f, toY=%f}".formatted(fromX, fromY, toX, toY);
}
}

View file

@ -1,6 +1,8 @@
module fr.emiko.graphicalapp { module fr.emiko.graphicalapp {
requires javafx.controls; requires javafx.controls;
requires javafx.fxml; requires javafx.fxml;
requires java.desktop;
requires org.controlsfx.controls;
opens fr.emiko.graphicalapp to javafx.fxml; opens fr.emiko.graphicalapp to javafx.fxml;

View file

@ -1,16 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?> <?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?> <VBox alignment="CENTER" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.emiko.graphicalapp.HelloController">
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml" <children>
fx:controller="fr.emiko.graphicalapp.HelloController"> <MenuBar VBox.vgrow="NEVER">
<padding> <menus>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/> <Menu mnemonicParsing="false" text="File">
</padding> <items>
<MenuItem fx:id="newCanvasButton" mnemonicParsing="false" text="New canvas" />
<Label fx:id="welcomeText"/> </items>
<Button text="Hello!" onAction="#onHelloButtonClick"/> </Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem fx:id="saveButton" mnemonicParsing="false" text="Save" />
<MenuItem fx:id="loadButton" mnemonicParsing="false" text="Load" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<SplitPane dividerPositions="0.11195652173913044" VBox.vgrow="ALWAYS">
<items>
<VBox prefHeight="200.0" prefWidth="100.0" />
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" />
<ColumnConstraints hgrow="SOMETIMES" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="ALWAYS" />
<RowConstraints vgrow="SOMETIMES" />
</rowConstraints>
<children>
<ScrollPane hbarPolicy="ALWAYS" style="-fx-background-color: #666666; -fx-background: #666666;" vbarPolicy="ALWAYS" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<content>
<Canvas fx:id="drawingCanvas" height="600.0" nodeOrientation="INHERIT" width="800.0" />
</content>
</ScrollPane>
</children>
</GridPane>
</items>
</SplitPane>
</children>
</VBox> </VBox>