fix(zoom): zoom rudimentaire fonctionnel avec scroll-bars fixées

This commit is contained in:
Emi Boucly 2025-03-17 16:41:29 +01:00
parent b325204d7d
commit 3f5bb98f8d
3 changed files with 98 additions and 50 deletions

View file

@ -1,27 +1,21 @@
package fr.emiko.graphicalapp; package fr.emiko.graphicalapp;
import javafx.application.Platform;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.event.EventHandler;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.Canvas; import javafx.scene.canvas.Canvas;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.canvas.GraphicsContext; import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane;
import javafx.scene.control.Slider; import javafx.scene.control.Slider;
import javafx.scene.image.PixelReader; import javafx.scene.input.*;
import javafx.scene.image.PixelWriter; import javafx.scene.layout.Pane;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.input.ZoomEvent;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import fr.emiko.graphicsElement.Stroke; import fr.emiko.graphicsElement.Stroke;
import javafx.scene.robot.Robot;
import javafx.scene.transform.Scale;
import java.awt.*;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.Vector; import java.util.Vector;
@ -34,10 +28,13 @@ public class HelloController implements Initializable {
public Slider brushSizeSlider; public Slider brushSizeSlider;
public Slider zoomSlider; public Slider zoomSlider;
public ScrollPane scrollPane; public ScrollPane scrollPane;
public Label brushSizeLabel;
public Pane pane;
private double posX = 0; private double posX = 0;
private double posY = 0; private double posY = 0;
private Vector<Stroke> strokes = new Vector<>(); private Vector<Stroke> strokes = new Vector<>();
private Vector<Stroke> lastSaved = new Vector<>(); private Vector<Stroke> lastSaved = new Vector<>();
private Vector<Vector<Stroke>> lines = new Vector<>();
@Override @Override
public void initialize(URL url, ResourceBundle resourceBundle) { public void initialize(URL url, ResourceBundle resourceBundle) {
@ -47,9 +44,51 @@ public class HelloController implements Initializable {
loadButton.setOnAction(this::onActionLoad); loadButton.setOnAction(this::onActionLoad);
newCanvasButton.setOnAction(this::onActionCreateCanvas); newCanvasButton.setOnAction(this::onActionCreateCanvas);
scrollPane.setOnScroll(this::onScrollZoom); scrollPane.setOnScroll(this::onScrollZoom);
scrollPane.getParent().setOnKeyPressed(this::onActionKeyPressed);
brushSizeLabel.textProperty().bind(brushSizeSlider.valueProperty().asString());
setupCanvas();
scrollPane.prefViewportHeightProperty().bind(pane.layoutYProperty());
scrollPane.prefViewportWidthProperty().bind(pane.layoutXProperty());
}
private void setupCanvas() {
drawingCanvas.requestFocus();
drawingCanvas.getGraphicsContext2D().setFill(Color.WHITE);
drawingCanvas.getGraphicsContext2D().fillRect(0, 0, drawingCanvas.getWidth(), drawingCanvas.getHeight());
brushSizeSlider.setValue(1);
drawingCanvas.setTranslateX(scrollPane.getWidth()/2);
drawingCanvas.setTranslateY(scrollPane.getHeight()/2);
scrollPane.addEventFilter(ScrollEvent.ANY, new EventHandler<ScrollEvent>() {
@Override
public void handle(ScrollEvent event) {
onScrollZoom(event);
event.consume();
}});
}
private void onActionKeyPressed(KeyEvent keyEvent) {
keyEvent.consume();
if (keyEvent.isControlDown() && keyEvent.getCode().equals(KeyCode.Z)) {
System.out.println("CTRL Z");
System.out.println(lines);
lines.remove(lines.lastElement());
GraphicsContext gc = drawingCanvas.getGraphicsContext2D();
gc.setFill(Color.WHITE);
gc.fillRect(0, 0, drawingCanvas.getWidth(), drawingCanvas.getHeight());
for (Vector<Stroke> strokeVector : lines) {
for (Stroke stroke: strokeVector) {
stroke.draw(gc);
System.out.println(stroke);
}
}
}
if (keyEvent.isControlDown() && keyEvent.getCode().equals(KeyCode.Y)) {
System.out.println("CTRL Y");
}
} }
private void onScrollZoom(ScrollEvent event) { private void onScrollZoom(ScrollEvent event) {
event.consume(); event.consume();
double SCALE_DELTA = 1.1; double SCALE_DELTA = 1.1;
if (event.getDeltaY() == 0) { if (event.getDeltaY() == 0) {
@ -59,15 +98,22 @@ public class HelloController implements Initializable {
double scaleFactor = double scaleFactor =
(event.getDeltaY() > 0) ? SCALE_DELTA : 1 / SCALE_DELTA; (event.getDeltaY() > 0) ? SCALE_DELTA : 1 / SCALE_DELTA;
drawingCanvas.setScaleX(drawingCanvas.getScaleX() * scaleFactor);
drawingCanvas.setScaleY(drawingCanvas.getScaleY() * scaleFactor);
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
Scale newScale = new Scale();
newScale.setX(drawingCanvas.getScaleX() * scaleFactor);
newScale.setY(drawingCanvas.getScaleY() * scaleFactor);
newScale.setPivotX(drawingCanvas.getScaleX());
newScale.setPivotY(drawingCanvas.getScaleY());
drawingCanvas.getTransforms().add(newScale);
System.out.println(pane.getHeight());
System.out.println(pane.getWidth());
pane.setPrefHeight(pane.getHeight()*scaleFactor);
pane.setPrefWidth(pane.getWidth()*scaleFactor);
} }
} }
private void onActionCreateCanvas(ActionEvent actionEvent) { private void onActionCreateCanvas(ActionEvent actionEvent) {
} }
@ -90,38 +136,29 @@ public class HelloController implements Initializable {
private void resetPos(MouseEvent mouseEvent) { private void resetPos(MouseEvent mouseEvent) {
posX = 0; posX = 0;
posY = 0; posY = 0;
lines.add((Vector<Stroke>) strokes.clone());
System.out.println(lines);
strokes.clear();
} }
private void printLine(MouseEvent mouseEvent) { private void printLine(MouseEvent mouseEvent) {
GraphicsContext gc = drawingCanvas.getGraphicsContext2D(); if (mouseEvent.isPrimaryButtonDown()) {
// gc.setFill(Color.BLACK); GraphicsContext gc = drawingCanvas.getGraphicsContext2D();
// gc.setStroke(Color.BLACK);
// gc.beginPath(); if (posX == 0 || posY == 0) {
// if (posX == 0 || posY == 0) { posX = mouseEvent.getX();
// posX = mouseEvent.getX(); posY = mouseEvent.getY();
// posY = mouseEvent.getY(); }
// }
// gc.moveTo(posX, posY); Stroke stroke = new Stroke(posX, posY, mouseEvent.getX(), mouseEvent.getY(), brushSizeSlider.getValue());
// gc.lineTo(mouseEvent.getX(), mouseEvent.getY()); strokes.add(stroke);
// gc.closePath(); stroke.draw(gc);
// gc.stroke();
// posX = mouseEvent.getX();
// posY = mouseEvent.getY();
if (posX == 0 || posY == 0) {
posX = mouseEvent.getX(); posX = mouseEvent.getX();
posY = mouseEvent.getY(); posY = mouseEvent.getY();
} else if (mouseEvent.isSecondaryButtonDown()) {
} }
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

@ -12,19 +12,21 @@ public class Stroke {
private final double fromY; private final double fromY;
private final double toX; private final double toX;
private final double toY; private final double toY;
private final double brushSize;
public Stroke (double fromX, double fromY, double toX, double toY) { public Stroke (double fromX, double fromY, double toX, double toY, double brushSize) {
this.fromX = fromX; this.fromX = fromX;
this.fromY = fromY; this.fromY = fromY;
this.toX = toX; this.toX = toX;
this.toY = toY; this.toY = toY;
this.brushSize = brushSize;
} }
public void draw (GraphicsContext g) { public void draw (GraphicsContext g) {
g.setStroke(javafx.scene.paint.Color.BLACK); g.setStroke(javafx.scene.paint.Color.BLACK);
g.setLineCap(StrokeLineCap.ROUND); g.setLineCap(StrokeLineCap.ROUND);
g.setMiterLimit(1); g.setMiterLimit(1);
g.setLineWidth(10); g.setLineWidth(brushSize);
g.setLineJoin(StrokeLineJoin.ROUND); g.setLineJoin(StrokeLineJoin.ROUND);
g.beginPath(); g.beginPath();
g.moveTo(fromX, fromY); g.moveTo(fromX, fromY);
@ -36,6 +38,6 @@ public class Stroke {
@Override @Override
public String toString () { public String toString () {
return "Stroke{fromX=%f, fromY=%f, toX=%f, toY=%f}".formatted(fromX, fromY, toX, toY); return "Stroke{fromX=%f, fromY=%f, toX=%f, toY=%f, brushSize=%f}".formatted(fromX, fromY, toX, toY, brushSize);
} }
} }

View file

@ -10,6 +10,7 @@
<?import javafx.scene.control.SplitPane?> <?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
@ -35,7 +36,7 @@
</Menu> </Menu>
</menus> </menus>
</MenuBar> </MenuBar>
<SplitPane dividerPositions="0.11195652173913044" VBox.vgrow="ALWAYS"> <SplitPane dividerPositions="0.16948784722222218" VBox.vgrow="ALWAYS">
<items> <items>
<VBox prefHeight="200.0" prefWidth="100.0"> <VBox prefHeight="200.0" prefWidth="100.0">
<children> <children>
@ -49,7 +50,7 @@
</rowConstraints> </rowConstraints>
<children> <children>
<Label text="Zoom" /> <Label text="Zoom" />
<Slider fx:id="zoomSlider" blockIncrement="0.1" max="5.0" min="1.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="1.0" GridPane.rowIndex="1" /> <Slider fx:id="zoomSlider" blockIncrement="0.1" majorTickUnit="5.0" max="5.0" min="1.0" minorTickCount="10" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="1.0" GridPane.rowIndex="1" />
</children> </children>
</GridPane> </GridPane>
<GridPane> <GridPane>
@ -61,8 +62,12 @@
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label text="Brush size" /> <Label fx:id="brushSizeLabel" text="1">
<Slider fx:id="brushSizeSlider" GridPane.rowIndex="1" /> <graphic>
<Label text="Brush Size :" />
</graphic>
</Label>
<Slider fx:id="brushSizeSlider" blockIncrement="1.0" majorTickUnit="5.0" max="10.0" minorTickCount="9" showTickLabels="true" showTickMarks="true" snapToTicks="true" GridPane.rowIndex="1" />
</children> </children>
</GridPane> </GridPane>
</children></VBox> </children></VBox>
@ -76,9 +81,13 @@
<RowConstraints vgrow="SOMETIMES" /> <RowConstraints vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<ScrollPane fx:id="scrollPane" hbarPolicy="ALWAYS" style="-fx-background-color: #666666; -fx-background: #666666;" vbarPolicy="ALWAYS" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS"> <ScrollPane fx:id="scrollPane" cache="true" cacheHint="QUALITY" depthTest="ENABLE" hbarPolicy="ALWAYS" style="-fx-background-color: #666666; -fx-background: #666666;" vbarPolicy="ALWAYS" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
<content> <content>
<Canvas fx:id="drawingCanvas" height="600.0" nodeOrientation="INHERIT" width="800.0" /> <Pane fx:id="pane">
<children>
<Canvas fx:id="drawingCanvas" height="600.0" nodeOrientation="INHERIT" width="800.0" />
</children>
</Pane>
</content> </content>
</ScrollPane> </ScrollPane>
</children> </children>