JavaFX - Какие панели использовать в приложении Paint на основе Canvas? - PullRequest
0 голосов
/ 23 апреля 2020

Здесь у меня есть приложение для рисования, которое должно уметь рисовать, создавать фигуры, стирать и очищать холст. У меня два вопроса:

Вопрос 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>
...