javafx 实现绘图板

利用javafx实现绘图板

实现功能包括绘制线条(直线、曲线)和几何图形,选中图形并反色,填充颜色,移动(线条移动有些不灵敏),计算长度面积、保存成可编辑文件、清空画板。
以前自己摸索写的,有很多不足,仅供自己使用

项目结构:

在这里插入图片描述

实现效果:

  1. 绘图
  2. 选中反色
    在这里插入图片描述
  3. 填充颜色
    在这里插入图片描述
  4. 计算面积
    List item
  5. 保存为可编辑文件
    在这里插入图片描述
    其他图就不放了。

源码:

package config;

public enum Action {
    SELECT, RECTANGULAR,MOVE,FILL,CIRCULAR,ELLIPSE,LINE,POLYLINE
}
package config;

import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import shape.*;

import java.io.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SaverLoader {
    ArrayList<String> arrayList;
    AnchorPane board;

    public SaverLoader() {

    }

    public ArrayList<String> getArrayList() {
        return arrayList;
    }

    public void setArrayList(ArrayList<String> arrayList) {
        this.arrayList = arrayList;
    }

    public AnchorPane getBoard() {
        return board;
    }

    public void setBoard(AnchorPane board) {
        this.board = board;
    }

    public void save() throws IOException {
        String time = String.valueOf(System.currentTimeMillis());
        DirectoryChooser directoryChooser = new DirectoryChooser();
        String path = String.valueOf(directoryChooser.showDialog(new Stage()).getAbsoluteFile());
        File file = new File(path + '\\' + time + ".edit");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(arrayList);

    }

    private void loadItem(String s) {
        String[] result = s.split(",");
        switch (result[0]) {
            case "MyPolyline":
                MyPolyline myPolyline = new MyPolyline(result[1], result[2], result[3], result[4], result[5], result[6], result[7]);
                board.getChildren().add(myPolyline);
                break;
            case "MyEllipse":
                MyEllipse myEllipse = new MyEllipse(result[1], result[2], result[3], result[4], result[5], result[6], result[7]);
                board.getChildren().add(myEllipse);
                break;
            case "MyCircular":
                MyCircular myCircular = new MyCircular(result[1], result[2], result[3], result[4], result[5], result[6]);
                board.getChildren().add(myCircular);
                break;
            case "MyRectangle":
                MyRectangle myRectangle = new MyRectangle(result[1], result[2], result[3], result[4], result[5], result[6], result[7]);
                board.getChildren().add(myRectangle);
                break;
            case "MyPath":
                ArrayList<Double> point = new ArrayList<>();
                for (int i = 5; i != result.length; ++i) point.add(Double.parseDouble(result[i]));
                MyPath myPath = new MyPath(result[1], result[2], result[3], result[4], point);
                board.getChildren().add(myPath);
                break;
            default:
                break;
        }
    }

    public void load() throws IOException, ClassNotFoundException {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Open Resource File");
        File file = fileChooser.showOpenDialog(new Stage());
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        ArrayList<String> p = ( ArrayList<String>) ois.readObject();
        board.getChildren().clear();
        for(String item:p){
            loadItem(item);
        }
    }

    public static void main(String[] args) throws ClassNotFoundException {

    }
}

package config;

import javafx.scene.paint.Color;

public class Setting {
    //填充
    Color fill;
    //边框
    Color stroke;
    //字体


    public Color getFill() {
        return fill;
    }

    public void setFill(Color fill) {
        this.fill = fill;
    }

    public Color getStroke() {
        return stroke;
    }

    public void setStroke(Color stroke) {
        this.stroke = stroke;
    }
}

package sample;

import config.Action;
import config.SaverLoader;
import config.Setting;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import shape.*;

import java.io.*;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.ResourceBundle;


public class Controller implements Initializable {
    public static Setting setting = new Setting();

    public static Action action = Action.SELECT;
    //鼠标点击坐标
    double p_x;
    double p_y;
    //鼠标抬起坐标
    double r_x;
    double r_y;
    //小数点坐标
    DecimalFormat df = new DecimalFormat("0.00");
    @FXML
    private javafx.scene.layout.AnchorPane AnchorPane;

    //画布
    @FXML
    private AnchorPane board;

    //图形
    @FXML
    private Button RectangularButton;

    @FXML
    private Button polyline;

    @FXML
    private Button circular;

    @FXML
    private Button ellipse;

    @FXML
    private Button line;

    //控件
    @FXML
    private javafx.scene.control.MenuBar MenuBar;

    @FXML
    private Label coordinate;

    @FXML
    private ColorPicker fillcolor;

    @FXML
    private ColorPicker strokecolor;

    //工具
    @FXML
    private Button fill;
    @FXML
    private Button SelectButton;
    @FXML
    private Button Move;
    MyPath path;
    //保存加载器
    SaverLoader saverLoader = new SaverLoader();

    @FXML
    void RectangularButton(MouseEvent event) {
        action = Action.RECTANGULAR;
    }

    @FXML
    void SelectButton(MouseEvent event) {
        action = Action.SELECT;
    }

    @FXML
    void Move(MouseEvent event) {
        action = Action.MOVE;
    }

    @FXML
    void fill(MouseEvent event) {
        action = Action.FILL;
    }

    @FXML
    void circular(MouseEvent event) {
        action = Action.CIRCULAR;
    }

    @FXML
    void ellipse(MouseEvent event) {
        action = Action.ELLIPSE;
    }

    @FXML
    void line(MouseEvent event) {
        action = Action.LINE;

    }

    @FXML
    void polyline(MouseEvent event) {
        action = Action.POLYLINE;
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        //菜单初始化
        {
            MenuBar.getMenus().get(0).getItems().get(0).setOnAction(
                    new EventHandler<ActionEvent>() {
                        public void handle(ActionEvent event) {
                            System.exit(0);
                        }
                    }
            );
            MenuBar.getMenus().get(0).getItems().get(1).setOnAction(
                    new EventHandler<ActionEvent>() {
                        public void handle(ActionEvent event) {

                            ArrayList<String> arrayList = new ArrayList<>();
                            for (Node i : board.getChildren()) arrayList.add(i.toString());
                            saverLoader.setBoard(board);
                            saverLoader.setArrayList(arrayList);
                            try {
                                saverLoader.save();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
            );
            MenuBar.getMenus().get(0).getItems().get(2).setOnAction(
                    new EventHandler<ActionEvent>() {
                        public void handle(ActionEvent event) {
                            saverLoader.setBoard(board);
                            try {
                                saverLoader.load();
                            } catch (IOException e) {
                                e.printStackTrace();
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            }
                        }
                    }
            );
            MenuBar.getMenus().get(1).getItems().get(0).setOnAction(
                    new EventHandler<ActionEvent>() {
                        public void handle(ActionEvent event) {
                            board.getChildren().clear();
                        }
                    }
            );
        }
        //初始化设置
        {
            setting.setStroke(Color.BLACK);
            setting.setFill(Color.web("#00000000"));
        }
        //填充颜色监听事件
        {
            fillcolor.setOnAction((event) -> {
                setting.setFill(fillcolor.getValue());
            });
        }
        //边框颜色监听事件
        {
            strokecolor.setOnAction((event) -> {
                setting.setStroke(strokecolor.getValue());
            });
        }
        board.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
            p_x = event.getX();
            p_y = event.getY();
            if (action == Action.LINE) {
                path = new MyPath(setting.getStroke());
                board.getChildren().add(path);
                path.getElements().add(new MoveTo(p_x, p_y));
                path.recordPoint(p_x, p_y);
            }
        });
        board.addEventHandler(MouseEvent.MOUSE_RELEASED, event -> {
            r_x = event.getX();
            r_y = event.getY();
            switch (action) {
                case RECTANGULAR:
                    MyRectangle myRectangle = new MyRectangle(p_x, p_y, r_x - p_x, r_y - p_y, setting.getFill(), setting.getStroke());
                    board.getChildren().add(myRectangle);
                    break;
                case CIRCULAR:
                    double r = Math.pow(Math.pow(r_x - p_x, 2) + Math.pow(r_y - p_y, 2), 0.5);
                    MyCircular myCircular = new MyCircular(p_x, p_y, r / 2, setting.getFill(), setting.getStroke());
                    board.getChildren().add(myCircular);
                    break;
                case POLYLINE:
                    MyPolyline myPolyline = new MyPolyline(setting.getStroke());
                    myPolyline.getPoints().addAll(p_x, p_y,
                            r_x, r_y);
                    board.getChildren().add(myPolyline);
//                    Polyline polyline = new Polyline();
//                    polyline.setStroke(setting.getStroke());
//                    polyline.getPoints().addAll(p_x, p_y,
//                            r_x, r_y);
//                    board.getChildren().add(polyline);
                    break;
                case ELLIPSE:
                    double a = Math.abs(r_x - p_x) / 2;
                    double b = Math.abs(r_y - p_y) / 2;
                    MyEllipse myEllipse = new MyEllipse(p_x, p_y, a, b, setting.getFill(), setting.getStroke());
                    board.getChildren().add(myEllipse);
                    break;
                default:
                    break;
            }
        });
        board.addEventHandler(MouseEvent.MOUSE_MOVED, event -> {
            coordinate.setText(String.format("x:%s px,y:%s px", df.format(event.getX()), df.format(event.getY())));
        });
        board.addEventHandler(MouseDragEvent.MOUSE_DRAGGED, event -> {
            if (action == Action.LINE) {
//                gc = Canvas.getGraphicsContext2D();
//                gc.setStroke(setting.getStroke());
//                gc.moveTo(p_x, p_y);
//                gc.lineTo(event.getX(), event.getY());
//                gc.stroke();
//                p_x = event.getX();
//                p_y = event.getY();
                path.setStroke(setting.getStroke());
                path.getElements().add(new LineTo(event.getX(), event.getY()));
                path.recordPoint(event.getX(), event.getY());
            }
        });
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {

    }
}

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("绘图板");
        primaryStage.getIcons().add(new Image("icon/logo.png"));
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

sample.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ColorPicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.paint.Color?>

<GridPane alignment="center" hgap="10" stylesheets="@win7glass.css" vgap="10" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <columnConstraints>
      <ColumnConstraints />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints />
   </rowConstraints>
   <children>
      <AnchorPane fx:id="AnchorPane" prefHeight="500.0" prefWidth="600.0">
         <children>
            <MenuBar fx:id="MenuBar" layoutY="2.0" prefHeight="14.0" prefWidth="600.0">
              <menus>
                <Menu mnemonicParsing="false" text="文件">
                  <items>
                    <MenuItem mnemonicParsing="false" text="关闭" />
                  </items>
                    <items>
                        <MenuItem mnemonicParsing="false" text="保存" />
                    </items>
                    <items>
                        <MenuItem mnemonicParsing="false" text="打开" />
                    </items>
                </Menu>
                <Menu mnemonicParsing="false" text="编辑">
                  <items>
                    <MenuItem mnemonicParsing="false" text="清空" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="帮助">
                  <items>
                    <MenuItem mnemonicParsing="false" text="关于" />
                  </items>
                </Menu>
              </menus>
            </MenuBar>
            <Button fx:id="RectangularButton" layoutY="28.0" mnemonicParsing="false" onMouseClicked="#RectangularButton" prefHeight="50.0" prefWidth="50.0" style="-fx-background-image:url('/icon/rectangleZ.png')" text="" />
            <Button fx:id="SelectButton" layoutY="403.0" mnemonicParsing="false" onMouseClicked="#SelectButton" prefHeight="50.0" prefWidth="50.0" style="-fx-background-image:url('/icon/select.png')" text="" />
            <AnchorPane fx:id="board" layoutX="100.0" layoutY="28.0" prefHeight="474.0" prefWidth="500.0" />
            <Label fx:id="coordinate" layoutX="399.0" layoutY="501.0" maxWidth="200.0" prefHeight="26.0" prefWidth="200.0" />
            <Button fx:id="Move" layoutX="-1.0" layoutY="453.0" mnemonicParsing="false" onMouseClicked="#Move" prefHeight="50.0" prefWidth="50.0" style="-fx-background-image:url('/icon/shapeCursor.png')" text="" />
            <ColorPicker fx:id="fillcolor" layoutY="324.0">
               <value>
                  <Color red="1.0" green="1.0" blue="1.0" opacity="0.0" />
               </value>
            </ColorPicker>
            <ColorPicker fx:id="strokecolor" layoutX="1.0" layoutY="380.0">
               <value>
                  <Color />
               </value>
            </ColorPicker>
            <Label alignment="CENTER" contentDisplay="CENTER" layoutX="-1.0" layoutY="290.0" prefHeight="33.0" prefWidth="100.0" text="填充颜色" textAlignment="CENTER" />
            <Label alignment="CENTER" layoutX="-1.0" layoutY="349.0" prefHeight="33.0" prefWidth="100.0" text="边框颜色" />
            <Button fx:id="fill" layoutX="50.0" layoutY="403.0" mnemonicParsing="false" onMouseClicked="#fill" prefHeight="50.0" prefWidth="50.0" style="-fx-background-image:url('/icon/barrel.png')" text="" />
            <Button fx:id="polyline" layoutY="128.0" mnemonicParsing="false" onMouseClicked="#polyline" prefHeight="50.0" prefWidth="50.0" style="-fx-background-image:url('/icon/line.png')" text="" />
            <Button fx:id="circular" layoutX="50.0" layoutY="28.0" mnemonicParsing="false" onMouseClicked="#circular" prefHeight="50.0" prefWidth="50.0" style="-fx-background-image:url('/icon/circular.png')" text="" />
            <Button fx:id="ellipse" layoutY="78.0" mnemonicParsing="false" onMouseClicked="#ellipse" prefHeight="50.0" prefWidth="50.0" style="-fx-background-image:url('/icon/oval.png')" text="" />
            <Button fx:id="line" layoutX="50.0" layoutY="78.0" mnemonicParsing="false" onMouseClicked="#line" prefHeight="50.0" prefWidth="50.0" style="-fx-background-image:url('/icon/pen.png')" text="" />
         </children>
      </AnchorPane>
   </children>
</GridPane>

package shape;

import config.Action;
import javafx.scene.control.Alert;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import sample.Controller;

import java.io.Serializable;

public class MyCircular extends Circle implements Serializable {
    double x;
    double y;
    private double fromX, fromY, lastTranslateX, lastTranslateY;
    Color fill;

    public MyCircular(double x, double y, double r, Color fill, Color stroke) {
        super(x, y, r);
        this.fill = fill;
        this.setFill(fill);
        this.setStroke(stroke);
        addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
            if (Controller.action == Action.MOVE) {
                fromX = event.getSceneX();
                fromY = event.getSceneY();
                lastTranslateX = getTranslateX();
                lastTranslateY = getTranslateY();
            }
            if (Controller.action == Action.SELECT) {
                setFill(this.fill.invert());
            }
            if (Controller.action == Action.FILL) {
                setFill(Controller.setting.getFill());
                this.fill = (Color) getFill();
            }
        });
        addEventHandler(MouseDragEvent.MOUSE_DRAGGED, event -> {
            if (Controller.action == Action.MOVE) {
                double deltaX = event.getSceneX() - fromX;
                double deltaY = event.getSceneY() - fromY;
                setTranslateX(deltaX + lastTranslateX);
                setTranslateY(deltaY + lastTranslateY);
            }
        });
        addEventHandler(MouseEvent.MOUSE_RELEASED, event -> {
            if (Controller.action == Action.SELECT) {
                setFill(this.fill);
            }
        });
        addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
            if (event.getButton().name().equals("SECONDARY") && Controller.action == Action.SELECT) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("面积");
                alert.setContentText("面积");
                alert.setHeaderText(String.valueOf(Math.PI*Math.pow(getRadius(),2))+"px^2");
                alert.showAndWait();
            }

        });
    }
    public MyCircular(String a, String b, String c, String d, String e, String f){
        this(Double.parseDouble(a),Double.parseDouble(b),Double.parseDouble(c),Color.web(d),Color.web(e));
    }
    @Override
    public String toString() {
        return "MyCircular,"+getCenterX()+","+getCenterY()+","+getRadius()+","+getFill()+","+getStroke()+","+getStrokeWidth();
    }
}

package shape;

import config.Action;
import javafx.scene.control.Alert;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import sample.Controller;

public class MyEllipse extends Ellipse {
    private double fromX, fromY, lastTranslateX, lastTranslateY;
    Color fill;

    public MyEllipse(double x, double y, double a, double b, Color fill, Color stroke) {
        super(x, y, a, b);
        this.fill = fill;
        this.setFill(fill);
        this.setStroke(stroke);
        addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
            if (Controller.action == Action.MOVE) {
                fromX = event.getSceneX();
                fromY = event.getSceneY();
                lastTranslateX = getTranslateX();
                lastTranslateY = getTranslateY();
            }
            if (Controller.action == Action.SELECT) {
                setFill(this.fill.invert());
            }
            if (Controller.action == Action.FILL) {
                setFill(Controller.setting.getFill());
                this.fill = (Color) getFill();
            }
        });
        addEventHandler(MouseDragEvent.MOUSE_DRAGGED, event -> {
            if (Controller.action == Action.MOVE) {
                double deltaX = event.getSceneX() - fromX;
                double deltaY = event.getSceneY() - fromY;
                setTranslateX(deltaX + lastTranslateX);
                setTranslateY(deltaY + lastTranslateY);
            }
        });
        addEventHandler(MouseEvent.MOUSE_RELEASED, event -> {
            if (Controller.action == Action.SELECT) {
                setFill(this.fill);
            }
        });
        addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
            if (event.getButton().name().equals("SECONDARY") && Controller.action == Action.SELECT) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("面积");
                alert.setContentText("面积");
                alert.setHeaderText(String.valueOf(Math.PI * getRadiusX() * getRadiusY()) + "px^2");
                alert.showAndWait();
            }

        });
    }

    public MyEllipse(String a, String b, String c, String d, String e, String f, String g) {
        this(Double.parseDouble(a),Double.parseDouble(b),Double.parseDouble(c),Double.parseDouble(d),Color.web(e),Color.web(f));
    }

    @Override
    public String toString() {
        return "MyEllipse," + getCenterX() + "," + getCenterY() + "," + getRadiusX() + "," + getRadiusY() + "," + getFill() + "," + getStroke() + "," + getStrokeWidth();
    }
}

package shape;

import config.Action;
import javafx.collections.ObservableList;
import javafx.scene.effect.Light;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.PathElement;
import sample.Controller;

import java.util.ArrayList;

public class MyPath extends Path {
    private double fromX, fromY, lastTranslateX, lastTranslateY;
    ArrayList<Double> point = new ArrayList<>();

    public void recordPoint(double a, double b) {
        point.add(a);
        point.add(b);
    }

    public MyPath(Color stroke) {
        super();
        this.setStroke(stroke);
        addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
            if (Controller.action == Action.MOVE) {
                fromX = event.getSceneX();
                fromY = event.getSceneY();
                lastTranslateX = getTranslateX();
                lastTranslateY = getTranslateY();
            }
        });
        addEventHandler(MouseDragEvent.MOUSE_DRAGGED, event -> {
            if (Controller.action == Action.MOVE) {
                double deltaX = event.getSceneX() - fromX;
                double deltaY = event.getSceneY() - fromY;
                setTranslateX(deltaX + lastTranslateX);
                setTranslateY(deltaY + lastTranslateY);
            }
        });
    }

    public MyPath(String a, String b, String c, String d, ArrayList<Double> points) {
        this(Color.web(c));
        this.getElements().add(new MoveTo(points.get(0), points.get(1)));
        for (int i = 2; i != points.size(); i += 2) {
            this.getElements().add(new LineTo(points.get(i), points.get(i + 1)));
        }
    }

    @Override
    public String toString() {
        String s = "MyPath," + getFill() + "," + getFillRule() + "," + getStroke() + "," + getStrokeWidth();
        for (Double p : point) {
            s += "," + p;
        }
        return s;
    }
}

package shape;

import config.Action;
import javafx.collections.ObservableList;
import javafx.scene.control.Alert;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polyline;
import sample.Controller;

import java.io.PrintWriter;

public class MyPolyline extends Polyline {
    private double fromX, fromY, lastTranslateX, lastTranslateY;

    public MyPolyline(Color stroke) {
        super();
        this.setStroke(stroke);
        addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
            if (Controller.action == Action.MOVE) {
                fromX = event.getSceneX();
                fromY = event.getSceneY();
                lastTranslateX = getTranslateX();
                lastTranslateY = getTranslateY();
            }
        });
        addEventHandler(MouseDragEvent.MOUSE_DRAGGED, event -> {
            if (Controller.action == Action.MOVE) {
                double deltaX = event.getSceneX() - fromX;
                double deltaY = event.getSceneY() - fromY;
                setTranslateX(deltaX + lastTranslateX);
                setTranslateY(deltaY + lastTranslateY);
            }
        });
        addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
            if (event.getButton().name().equals("SECONDARY") && Controller.action == Action.SELECT) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("长度");
                alert.setContentText("长度");
                double ap = Math.pow(getPoints().get(0) - getPoints().get(2),2);
                double bp = Math.pow(getPoints().get(1) - getPoints().get(3),2);
                alert.setHeaderText(String.valueOf(Math.pow(ap+bp,0.5)+"px"));
                alert.showAndWait();
            }

        });
    }

    public MyPolyline(String a, String b, String c, String d, String e, String f, String g) {
        this(Color.web(f));
        getPoints().addAll(Double.parseDouble(a),Double.parseDouble(b),Double.parseDouble(c),Double.parseDouble(d));
        setStrokeWidth(Double.parseDouble(g));
    }

    @Override
    public String toString() {
        return "MyPolyline," + getPoints().get(0) + "," + getPoints().get(1) + "," + getPoints().get(2) + "," + getPoints().get(3) + "," + getFill() + "," + getStroke() + "," + getStrokeWidth();
    }
}

package shape;

import config.Action;
import config.Setting;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import sample.Controller;

import java.net.URL;
import java.util.ResourceBundle;

public class MyRectangle extends javafx.scene.shape.Rectangle {
    double x;
    double y;
    private double fromX, fromY, lastTranslateX, lastTranslateY;
    Color fill;

    public MyRectangle(double x, double y, double w, double h, Color fill, Color stroke) {
        super(x, y, w, h);
        this.fill = fill;
        this.setFill(fill);
        this.setStroke(stroke);
        addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
            if (Controller.action == Action.MOVE) {
                fromX = event.getSceneX();
                fromY = event.getSceneY();
                lastTranslateX = getTranslateX();
                lastTranslateY = getTranslateY();
            }
            if (Controller.action == Action.SELECT) {
                setFill(this.fill.invert());
            }
            if(Controller.action == Action.FILL){
                setFill(Controller.setting.getFill());
                this.fill = (Color) getFill();
            }
        });
        addEventHandler(MouseDragEvent.MOUSE_DRAGGED, event -> {
            if (Controller.action == Action.MOVE) {
                double deltaX = event.getSceneX() - fromX;
                double deltaY = event.getSceneY() - fromY;
                setTranslateX(deltaX + lastTranslateX);
                setTranslateY(deltaY + lastTranslateY);
            }
        });
        addEventHandler(MouseEvent.MOUSE_RELEASED, event -> {
            if (Controller.action == Action.SELECT) {
                setFill(this.fill);
            }
        });
        addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
            if (event.getButton().name().equals("SECONDARY") && Controller.action == Action.SELECT) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("面积");
                alert.setContentText("面积");
                alert.setHeaderText(String.valueOf(getWidth()*getHeight())+"px^2");
                alert.showAndWait();
            }

        });
    }
    public MyRectangle(String a, String b, String c, String d, String e, String f, String g){
        this(Double.parseDouble(a),Double.parseDouble(b),Double.parseDouble(c),Double.parseDouble(d),Color.web(e),Color.web(f));
    }
    @Override
    public String toString() {
        return "MyRectangle,"+getX()+","+getY()+","+getWidth()+","+getHeight()+","+getFill()+","+getStroke()+","+getStrokeWidth();
    }
}

css样式比较丑,可以自己设计一下

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在JavaFX实现画板擦除功能可以通过以下步骤来实现: 首先,创建一个JavaFX的画板对象来支持绘图和擦除功能。画板可以通过Canvas来创建。 然后,设置画板的大小和背景颜色,以及添加到JavaFX的场景中显示出来。 接着,定义一个变量来表示是否正在绘制(即鼠标按下时)或者擦除(即按住Ctrl键时鼠标按下)。根据这个变量来确定鼠标拖动时是绘制还是擦除的操作。 接下来,注册鼠标按下、拖动和释放事件的处理程序。当鼠标按下时,根据是否按住Ctrl键来设置绘制还是擦除的模式,并记录下鼠标的位置。当鼠标拖动时,根据模式来绘制或擦除画板上的图形。当鼠标释放时,结束绘制或擦除操作。 最后,将画板添加到JavaFX的窗口中,并显示出来。 通过以上步骤,就可以在JavaFX实现画板擦除功能。用户可以根据需要选择绘制还是擦除模式,并通过鼠标拖动来实现在画板上进行绘制或擦除操作。 ### 回答2: JavaFX实现画板擦除功能可以通过以下步骤实现: 1. 创建一个JavaFX的画板应用程序。 2. 在画板上使用JavaFX的绘图工具来绘制图形和文字。 3. 实现擦除功能的关键是使用GraphicsContext的clearRect方法。该方法接受四个参数:起始点的x坐标、y坐标,以及矩形的宽度和高度。调用这个方法可以清除指定区域的图形。 4. 当用户点击画板上的“擦除”按钮时,设置一个标志来指示擦除模式已启用。 5. 在鼠标按下事件处理程序中,检查擦除模式是否已启用。如果是,则将擦除标志设置为真,并使用clearRect方法擦除鼠标所在的位置。 6. 在鼠标拖动事件处理程序中,如果擦除标志为真,则使用clearRect方法擦除鼠标所在的位置。 7. 在鼠标释放事件处理程序中,将擦除标志设置为假,擦除操作完成。 8. 实现其他必要的功能,如画笔颜色、粗细的调整等。 通过以上步骤,就可以实现JavaFX画板擦除功能。当用户使用鼠标进行绘画操作时,可以通过点击擦除按钮来切换到擦除模式,在该模式下使用鼠标进行擦除操作。这样就可以实现画板擦除功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值