JavaFX实现简易的画图程序

JavaFX实现一个简易的画图程序

为了应付学校的JavaFX作业瞎写了一个非常简单的画图程序。有很多提高和优化的空间,有需要的可以参考下优化,才疏学浅,希望读者不吝赐教。

基本的属性资源接口

import javafx.scene.paint.Color;

/**
 * @author Mr.X
 */
public interface PropertyInterface {
    double stageWidth = 900;
    double stageHeight = 600;
    double[] strokeWidths = new double[]{1, 5, 15};

    Color[] strokeColors = new Color[]{Color.BLACK, Color.RED, Color.YELLOW, Color.BLUE};

    int[] commands = new int[]{0, 1, 2, 3};
}

MenuBar工厂类

import javafx.embed.swing.SwingFXUtils;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.image.WritableImage;
import javafx.scene.input.KeyCombination;
import javafx.scene.paint.Color;
import javafx.stage.FileChooser;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

/**
 * @ClassName MenuBarFactory
 * @Description TODO
 * @Author Mr_X
 * @Date 2022/4/29 9:26
 * @Version 1.0
 */
public class MenuBarFactory implements PropertyInterface{
    double strokeWidth = strokeWidths[0];
    Color strokeColor = strokeColors[0];
    int command = commands[0];


    private CanvasFactory canvasFactory = new CanvasFactory();
    private Canvas canvas;
    private GraphicsContext gc;
    private MenuBar menuBar ;
    WritableImage snapshot;




    public MenuBarFactory(MenuBar menuBar,CanvasFactory canvasFactory) {
        this.menuBar = menuBar;
        this.canvasFactory = canvasFactory;
        canvas = canvasFactory.getCanvas();
        gc = canvasFactory.getGc();
    }



    public MenuBarFactory(CanvasFactory canvasFactory) {
        menuBar = new MenuBar();
        this.canvasFactory = canvasFactory;
        canvas = canvasFactory.getCanvas();
        gc = canvasFactory.getGc();

        Menu menu0 = new Menu("颜色");
        Menu menu1 = new Menu("粗细");
        Menu menu2 = new Menu("图形");
        Menu menu3 = new Menu("快捷工具");


        MenuItem colorR = new MenuItem("红色");
        colorR.setOnAction(e -> canvasFactory.setStrokeColor(strokeColors[1]));


        MenuItem colorY = new MenuItem("黄色");
        colorY.setOnAction(e -> canvasFactory.setStrokeColor(strokeColors[2]));

        MenuItem colorB = new MenuItem("蓝色");
        colorB.setOnAction(e -> canvasFactory.setStrokeColor(strokeColors[3]));

        MenuItem colorD = new MenuItem("黑色");
        colorD.setOnAction(e -> canvasFactory.setStrokeColor(strokeColors[0]));

        menu0.getItems().addAll(colorD, colorR, colorB, colorY);


        MenuItem borderT = new MenuItem("粗");
        borderT.setOnAction(e -> canvasFactory.setStrokeWidth(strokeWidths[2]));
        MenuItem borderM = new MenuItem("中");
        borderM.setOnAction(e -> canvasFactory.setStrokeWidth(strokeWidths[1]));
        MenuItem borderS = new MenuItem("细");
        borderS.setOnAction(e -> canvasFactory.setStrokeWidth(strokeWidths[0]));
        menu1.getItems().addAll(borderS, borderM, borderT);


        MenuItem spaceD = new MenuItem("默认");
        spaceD.setOnAction(e -> canvasFactory.setCommand(commands[0]));
        MenuItem spaceR = new MenuItem("矩形");
        spaceR.setOnAction(e -> canvasFactory.setCommand(commands[1]));
        MenuItem spaceE = new MenuItem("椭圆");
        spaceE.setOnAction(e -> canvasFactory.setCommand(commands[2]));
        MenuItem spaceL = new MenuItem("直线");
        spaceL.setOnAction(e -> canvasFactory.setCommand(commands[3]));
        menu2.getItems().addAll(spaceD, spaceR, spaceE, spaceL);


        MenuItem manageC = new MenuItem("清空");
        MenuItem manageS = new MenuItem("另存为");
        //设置快捷键
        manageC.setAccelerator(KeyCombination.valueOf("ctrl+alt+c"));
        manageS.setAccelerator(KeyCombination.valueOf("ctrl+s"));
        menu3.getItems().addAll(manageC, manageS);



        manageC.setOnAction(event -> {
            ArrayList<Double> canvasProperty = canvasFactory.getCanvasProperty();
            gc.clearRect(0, 0, canvas.getWidth(),canvas.getHeight());
            snapshot = null;
        });


        manageS.setOnAction(event -> {
            snapshot = canvas.snapshot(null, null);
            BufferedImage bufferedImage = SwingFXUtils.fromFXImage(snapshot, null);

            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("保存canvas图片");
            fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("PNG", ".png"));

            File file = fileChooser.showSaveDialog(canvas.getScene().getWindow());

            if (file != null) {
                try {
                    ImageIO.write(bufferedImage, "PNG", file);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        });




        menuBar.getMenus().addAll(menu3, menu0, menu1, menu2);
        menuBar.setPrefWidth(stageWidth);
    }

    public MenuBar getMenuBar() {
        return menuBar;
    }
}

Canvas工厂类

import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;

import java.util.ArrayList;

/**
 * @ClassName CanvasFactory
 * @Description TODO
 * @Author Mr_X
 * @Date 2022/4/29 9:34
 * @Version 1.0
 */
public class CanvasFactory implements PropertyInterface{

    double strokeWidth = strokeWidths[0];
    Color strokeColor = strokeColors[0];
    int command = commands[0];
    double canvasWidth;
    double canvasHeight;
    ArrayList<Double> properties;

    private WritableImage snapshot;

    //记录鼠标落下的坐标点
    double startX;
    double startY;

    final Canvas canvas;
    final GraphicsContext gc;



    public CanvasFactory(Canvas canvas) {
        this.canvas = canvas;
        canvas.setLayoutX(0.0);
        canvas.setLayoutY(0.0);
        gc = canvas.getGraphicsContext2D();
    }

    public CanvasFactory() {
        canvas = new Canvas(stageWidth,stageHeight);
        gc = canvas.getGraphicsContext2D();
    }

    public Canvas getCanvas() {
        return canvas;
    }

    public GraphicsContext getGc() {
        return gc;
    }


    public void setStrokeWidth(double strokeWidth) {
        this.strokeWidth = strokeWidth;
    }

    public void setStrokeColor(Color strokeColor) {
        this.strokeColor = strokeColor;
    }

    public void setCommand(int command) {
        this.command = command;
    }

    public void mouseListenerPaint(){


        //鼠标落下即可得到起始位置的坐标点
        canvas.setOnMousePressed(event -> {
            startX = event.getX();
            startY = event.getY();
        });
        //监听鼠标拖拽来绘制图形
        canvas.setOnMouseDragged(event -> {
            properties = getCanvasProperty();

            double beginX = startX;
            double beginY = startY;

            double endX = event.getX();
            double endY = event.getY();
            gc.setStroke(strokeColor);
            gc.setLineWidth(strokeWidth);
            if (command == 1) {

                if (endX < startX) {
                    beginX = endX;
                    endX = startX;
                }
                if (endY < startY) {
                    beginY = endY;
                    endY = startY;
                }
                gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());

                gc.drawImage(snapshot, 0, 0, canvas.getWidth(), canvas.getHeight());

                gc.strokeRect(beginX, beginY, endX - beginX, endY - beginY);

            } else if (command == 0) {

                gc.strokeLine(startX, startY, endX, endY);

                startX = endX;
                startY = endY;
            } else if (command == 3) {
                gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
                gc.drawImage(snapshot, 0, 0, canvas.getWidth(), canvas.getHeight());
                gc.strokeLine(startX, startY, endX, endY);
            } else if (command == 2) {
                if (endX < startX) {
                    beginX = endX;
                    endX = startX;
                }
                if (endY < startY) {
                    beginY = endY;
                    endY = startY;
                }
                gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
                gc.drawImage(snapshot, 0, 0, canvas.getWidth(), canvas.getHeight());
                gc.strokeOval(beginX, beginY, endX - beginX, endY - beginY);
            }


        });
        //鼠标落下后将canvas的内容通过快照来记录,但是这也造成一个问题,随着绘次数最多会造成画面失真
        canvas.setOnMouseReleased(event -> snapshot = canvas.snapshot(null, null));

    }

    public ArrayList<Double> getCanvasProperty(){
        //监听画布的长高属性并返回。
        canvas.widthProperty().addListener((observable, oldValue, newValue) -> canvasWidth = newValue.doubleValue());
        canvas.heightProperty().addListener((observable, oldValue, newValue) -> canvasHeight = newValue.doubleValue());
        ArrayList<Double> properties = new ArrayList<>();
        properties.add(canvasWidth);
        properties.add(canvasHeight);
        return properties;
    }
}

Painter入口类

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.MenuBar;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.io.InputStream;
/**
 * @ClassName PainterTest
 * @Description TODO
 * @Author Mr_X
 * @Date 2022/4/29 9:24
 * @Version 1.0
 */


public class PainterTest extends Application implements PropertyInterface{
    static {
        System.out.println("这是静态代码块\t"+Thread.currentThread().getName());
    }
    final CanvasFactory canvasFactory = new CanvasFactory();
    final MenuBarFactory menuBarFactory = new MenuBarFactory(canvasFactory);
    final  MenuBar menuBar = menuBarFactory.getMenuBar();
    final Canvas canvas = canvasFactory.getCanvas();


    public static void main(String[] args) {
        System.out.println("这是main方法\t"+Thread.currentThread().getName());
        launch(args);
    }


    @Override
    public void init() throws Exception {
        System.out.println("这是初始化方法\t"+Thread.currentThread().getName());
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        System.out.println("这是start方法\t"+Thread.currentThread().getName());

        canvasFactory.mouseListenerPaint();



        AnchorPane anchorPane = new AnchorPane();
        anchorPane.setPrefHeight(stageHeight);
        anchorPane.setPrefWidth(stageWidth);
        anchorPane.getChildren().add(canvas);


        BorderPane borderPane = new BorderPane();
        borderPane.setTop(menuBar);
        borderPane.setCenter(anchorPane);


        Scene scene = new Scene(borderPane);
        primaryStage.setScene(scene);
        primaryStage.setTitle(this.getClass().getSimpleName());
        primaryStage.setHeight(stageHeight);
        primaryStage.setWidth(stageWidth);
     
        primaryStage.show();

        //动态调整画布的长宽
        primaryStage.widthProperty().addListener((observable, oldValue, newValue) -> {
            anchorPane.setPrefWidth(newValue.doubleValue());
            canvas.setWidth(anchorPane.getWidth());
        });
        primaryStage.heightProperty().addListener((observable, oldValue, newValue) -> {
            anchorPane.setPrefHeight(newValue.doubleValue());
            canvas.setHeight(anchorPane.getHeight());
        });


    }


    @Override
    public void stop() throws Exception {
        System.out.println("这是stop方法\t"+Thread.currentThread().getName());
    }
}

测试效果

效果图

注: 文件结构

包结构

传送门==》

Javafx完美复刻记事本

  • 10
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值