You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Java OOP,如何实现类MS Paint绘图应用的文件操作功能?

Java类MS Paint绘图应用文件操作与设计优化

一、数据结构选择

  1. 画布图形存储:使用ArrayList<Shape>完全足够,它能按绘图顺序存储所有图形,支持快速增删和遍历,符合绘图应用的需求。
  2. 最近文件列表:用静态ArrayList<String>存储路径,限制最大数量(比如5个),更新时将最新文件移到头部,超过上限则移除最旧的,保证列表只保留最近的文件记录。

二、核心类修改(为持久化做准备)

当前的Shape接口和实现类仅返回描述字符串,无法保存图形状态(比如颜色),需要调整为持有状态的设计:

1. 修改Shape接口

import java.io.Serializable;

public interface Shape extends Serializable {
    String draw();
    void setColor(String color);
    String getColor();
}

添加Serializable接口支持序列化,同时将color()方法拆分为setColor和getColor,用于存储和读取颜色属性。

2. 实现类示例(Line)

public class Line implements Shape {
    private String color;

    @Override
    public String draw() {
        return "Line is drawn";
    }

    @Override
    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String getColor() {
        return color;
    }
}

Circle和Rectangle类做同样修改,添加color成员变量并实现对应的set/get方法。

三、Paint类完善(添加文件操作)

修改Paint类,添加图形管理和文件操作功能:

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Paint implements Serializable {
    private List<Shape> shapes;
    private static final int MAX_RECENT_FILES = 5;
    private static List<String> recentFiles = new ArrayList<>(MAX_RECENT_FILES);

    public Paint() {
        shapes = new ArrayList<>();
    }

    // 添加图形到画布
    public void addShape(Shape shape) {
        shapes.add(shape);
    }

    // 绘制直线并加入画布
    public Line drawLine() {
        Line line = new Line();
        addShape(line);
        return line;
    }

    // 绘制圆形并加入画布
    public Circle drawCircle() {
        Circle circle = new Circle();
        addShape(circle);
        return circle;
    }

    // 绘制矩形并加入画布
    public Rectangle drawRectangle() {
        Rectangle rectangle = new Rectangle();
        addShape(rectangle);
        return rectangle;
    }

    // 新建文件:清空当前画布
    public void newFile() {
        shapes.clear();
    }

    // 保存文件:序列化整个Paint对象到文件
    public void saveFile(String filePath) throws IOException {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath))) {
            oos.writeObject(this);
            updateRecentFiles(filePath);
        }
    }

    // 打开文件:从文件反序列化生成Paint对象
    public static Paint openFile(String filePath) throws IOException, ClassNotFoundException {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {
            Paint paint = (Paint) ois.readObject();
            updateRecentFiles(filePath);
            return paint;
        }
    }

    // 获取最近打开/保存的文件列表
    public static List<String> getRecentFiles() {
        return new ArrayList<>(recentFiles); // 返回副本避免外部修改内部状态
    }

    // 更新最近文件列表:去重+保持最新在前+限制数量
    private static void updateRecentFiles(String filePath) {
        recentFiles.remove(filePath);
        recentFiles.add(0, filePath);
        if (recentFiles.size() > MAX_RECENT_FILES) {
            recentFiles.remove(recentFiles.size() - 1);
        }
    }

    // 获取当前画布的所有图形(返回副本)
    public List<Shape> getShapes() {
        return new ArrayList<>(shapes);
    }
}

关键功能说明

  • 新建文件:直接清空shapes列表,重置画布状态。
  • 保存文件:通过ObjectOutputStream将整个Paint对象序列化写入文件,自动保存所有图形的颜色等状态;同时更新最近文件列表。
  • 打开文件:通过ObjectInputStream读取文件并反序列化为Paint对象,恢复之前的画布状态;同样更新最近文件列表。
  • 最近文件管理:静态列表存储全局的最近文件记录,更新时保证列表有序且不超过最大数量。

四、使用示例

import java.util.List;

public class Main {
    public static void main(String[] args) {
        try {
            // 创建画布并绘制图形
            Paint paint = new Paint();
            Line redLine = paint.drawLine();
            redLine.setColor("red");
            Circle blueCircle = paint.drawCircle();
            blueCircle.setColor("blue");

            // 保存文件
            paint.saveFile("my_drawing.paint");

            // 新建文件
            paint.newFile();
            System.out.println("新建后图形数量:" + paint.getShapes().size()); // 输出0

            // 打开保存的文件
            Paint loadedPaint = Paint.openFile("my_drawing.paint");
            System.out.println("打开后图形数量:" + loadedPaint.getShapes().size()); // 输出2
            System.out.println("直线颜色:" + ((Line) loadedPaint.getShapes().get(0)).getColor()); // 输出red

            // 查看最近文件
            List<String> recent = Paint.getRecentFiles();
            System.out.println("最近文件:" + recent); // 输出[my_drawing.paint]
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

五、替代方案(自定义文本格式)

如果不想用Java原生序列化,可自定义文本格式存储图形信息(比如每行格式:图形类型,颜色),适合需要可读文件的场景:

自定义保存/打开方法

// 自定义格式保存
public void saveFileCustom(String filePath) throws IOException {
    try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
        for (Shape shape : shapes) {
            String type = shape.getClass().getSimpleName();
            String color = shape.getColor() == null ? "default" : shape.getColor();
            writer.write(type + "," + color);
            writer.newLine();
        }
        updateRecentFiles(filePath);
    }
}

// 自定义格式打开
public static Paint openFileCustom(String filePath) throws IOException {
    Paint paint = new Paint();
    try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
        String line;
        while ((line = reader.readLine()) != null) {
            String[] parts = line.split(",");
            if (parts.length < 1) continue;
            Shape shape = switch (parts[0]) {
                case "Line" -> new Line();
                case "Circle" -> new Circle();
                case "Rectangle" -> new Rectangle();
                default -> null;
            };
            if (shape != null && parts.length >= 2) {
                shape.setColor(parts[1]);
                paint.addShape(shape);
            }
        }
        updateRecentFiles(filePath);
    }
    return paint;
}

这种方式的优点是文件可读可编辑,但如果后续需要添加图形的位置、大小等属性,解析逻辑会更复杂,序列化方式则能自动处理所有属性的持久化。

内容的提问来源于stack exchange,提问作者arin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 21:39:36