Здесь у меня есть приложение для рисования, которое должно уметь рисовать, создавать фигуры, стирать и очищать холст. У меня два вопроса:
Вопрос 1 Как лучше всего передать фигуры панели / холсту в контроллере, не стирая все остальное после прорисовки?
Вопрос 2 Как лучше всего настроить панели в моем файле F XML, чтобы функция рисования dr aws на холсте, фигуры добавлялись как объекты на панель (чтобы они могут быть отредактированы после размещения), и функция очистки, чтобы просто очистить формы и рисунки?
Спасибо.
Контроллер
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXML;
import javafx.scene.Group;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javax.imageio.ImageIO;
import java.io.File;
public class Controller {
double startX, startY, prevX, prevY, currentX, currentY;
boolean dragging, newRectBeingDrawn, newEllipseBeingDrawn;
Rectangle newRectangle = null;
Ellipse newEllipse = null;
Group shapeArray = new Group();
@FXML private BorderPane rootPane;
@FXML private ScrollPane canvasSP = new ScrollPane();
@FXML private Canvas canvas;
@FXML private Button clearCanvas;
@FXML private ColorPicker colorPickerFill;
@FXML private ColorPicker colorPickerStroke;
@FXML private TextField brushSize;
@FXML private ToggleButton transform;
@FXML private ToggleButton eraser;
@FXML private ToggleButton brush;
@FXML private ToggleButton rectangle;
@FXML private ToggleButton ellipse;
@FXML private CheckBox filled;
public void initialize() {
GraphicsContext g = canvas.getGraphicsContext2D();
g.setFill(Color.BEIGE);
canvas.setOnMousePressed(e -> {
startX = prevX = currentX = e.getSceneX();
startY = prevY = currentY = e.getSceneY();
dragging = true;
if(rectangle.isSelected()) {
if (newRectBeingDrawn != true) {
newRectangle = new Rectangle();
newRectangle.setFill(Color.GRAY);
newRectangle.setStroke(colorPickerStroke.getValue());
newRectangle.setStrokeWidth(Double.parseDouble(brushSize.getText()));
canvasSP.setContent(canvas);
newRectBeingDrawn = true;
}
}
if(ellipse.isSelected()) {
if (newEllipseBeingDrawn != true) {
newEllipse = new Ellipse();
newEllipse.setFill(Color.GRAY);
newEllipse.setStroke(colorPickerStroke.getValue());
newEllipse.setStrokeWidth(Double.parseDouble(brushSize.getText()));
newEllipseBeingDrawn = true;
}
}
clearCanvas.setOnAction(event -> {
g.setFill(Color.BEIGE);
g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
});
});
canvas.setOnMouseDragged(e -> {
double size = Double.parseDouble(brushSize.getText());
if(!dragging)
return;
currentX = e.getSceneX();
currentY = e.getSceneY();
if (eraser.isSelected()) {
g.clearRect(currentX, currentY, size, size);
} else if (brush.isSelected()) {
g.setStroke(colorPickerStroke.getValue());
g.setLineWidth(size);
g.strokeLine(prevX, prevY, currentX, currentY);
} else if (rectangle.isSelected()) {
if(newRectBeingDrawn == true) {
double currentEndingPointX = e.getSceneX();
double currentEndingPointY = e.getSceneY();
adjustRectangle(startX, startY,
currentEndingPointX, currentEndingPointY, newRectangle);
}
} else if (ellipse.isSelected()) {
if(newEllipseBeingDrawn == true) {
double currentEndingPointX = e.getSceneX();
double currentEndingPointY = e.getSceneY();
adjustEllipse(startX, startY,
currentEndingPointX, currentEndingPointY, newEllipse);
}
}
prevX = currentX;
prevY = currentY;
});
canvas.setOnMouseReleased(e -> {
dragging = false;
if(newRectBeingDrawn == true) {
if(filled.isSelected() == true ) {
newRectangle.setFill(colorPickerFill.getValue());
} else {
newRectangle.setFill(Color.TRANSPARENT);
}
newRectangle = null;
newRectBeingDrawn = false;
}
if(newEllipseBeingDrawn == true) {
if(filled.isSelected() == true ) {
newEllipse.setFill(colorPickerFill.getValue());
} else {
newEllipse.setFill(Color.TRANSPARENT);
}
newEllipse = null;
newEllipseBeingDrawn = false;
}
});
}
void adjustRectangle (double startX,
double startY,
double prevX,
double prevY,
Rectangle given_rectangle) {
given_rectangle.setX( startX );
given_rectangle.setY( startY );
given_rectangle.setWidth( prevX - startX ) ;
given_rectangle.setHeight( prevY - startY ) ;
if ( given_rectangle.getWidth() < 0 ) {
given_rectangle.setWidth( - given_rectangle.getWidth() ) ;
given_rectangle.setX( given_rectangle.getX() - given_rectangle.getWidth() ) ;
}
if ( given_rectangle.getHeight() < 0 ) {
given_rectangle.setHeight( - given_rectangle.getHeight() ) ;
given_rectangle.setY( given_rectangle.getY() - given_rectangle.getHeight() ) ;
}
}
void adjustEllipse (double startX,
double startY,
double prevX,
double prevY,
Ellipse given_ellipse) {
given_ellipse.setCenterX( startX );
given_ellipse.setCenterY( startY );
given_ellipse.setRadiusX( prevX - startX ) ;
given_ellipse.setRadiusY( prevY - startY ) ;
if ( given_ellipse.getRadiusX() < 0 ) {
given_ellipse.setRadiusX( - given_ellipse.getRadiusX() ) ;
given_ellipse.setCenterX( given_ellipse.getCenterX() - given_ellipse.getRadiusX() ) ;
}
if ( given_ellipse.getRadiusY() < 0 ) {
given_ellipse.setRadiusY( - given_ellipse.getRadiusY() ) ;
given_ellipse.setCenterY( given_ellipse.getCenterY() - given_ellipse.getRadiusY() ) ;
}
}
public void onSave() {
try {
Image snapshot = canvas.snapshot(null, null);
ImageIO.write(SwingFXUtils.fromFXImage(snapshot, null), "png", new File("paintsave.png"));
} catch (Exception e) {
System.out.println("Failed to save: " + e);
}
}
public void onExit() {
Platform.exit();
}
}
F XML
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ColorPicker?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.control.ScrollPane?>
<BorderPane id ="BorderPane" fx:id="rootPane" fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml"
prefHeight="600.0" prefWidth="600.0">
<top>
<VBox>
<MenuBar>
<Menu text="file">
<MenuItem text="Save" onAction="#onSave"/>
<MenuItem text="Exit" onAction="#onExit"/>
</Menu>
</MenuBar>
</VBox>
</top>
<left>
<ToolBar>
<VBox spacing="1" >
<TextField fx:id="brushSize" text="18"/>
<ColorPicker fx:id="colorPickerFill" accessibleText="Fill"/>
<ColorPicker fx:id="colorPickerStroke" accessibleText="Stroke"/>
<Button fx:id="clearCanvas" text="Clear Canvas" prefWidth="50"/>
<ToggleButton fx:id="transform" text="Transform"/>
<ToggleButton fx:id="brush" text="Brush"/>
<ToggleButton fx:id="eraser" text="Eraser"/>
<ToggleButton fx:id="rectangle" text="Rectangle"/>
<ToggleButton fx:id="ellipse" text="Ellipse"/>
<CheckBox fx:id="filled" text="Filled?"/>
</VBox>
</ToolBar>
</left>
<center>
<ScrollPane fx:id="canvasSP" prefWidth="600" prefHeight="600">
<Canvas fx:id="canvas" width="600" height="600"/>
</ScrollPane>
</center>
</BorderPane>