画图板自定义格式保存
文件格式:
我们都知道任何一种文件都有各自的格式,譬如图片格式有: png,bmp,jpeg,gif; 视频格式有: flv , rmvb,mp4,avi,dvd 等等。相同类型的文件其格式的不同其实质是文件的信息用不同的顺序和表达写到存储器中,然后读去该文件时以与存储相同的顺序读取文件的信息。
该项目即用自定义的文件格式实现画图板所绘制图形的保存与读取;
该项目是在原来画图板制作以及重回完成的基础上进行的操作。
一、 创建一个文件操作的类定义文件存储与打开的方法:
/**
* 定义一个画板保存和读取的类
*/
public class FileUtil {
String path = " 保存路径 ";
Arrayexe<Shape> shapes = new Arrayexe<Shape>();
/**
* 定义一个文件保存的方法
*
* @param path
* 文件要保存的位置
* @param shapes 要传入的信息
* @return
*/
public boolean saveFile(String path, Arrayexe<Shape> shapes) {
try {
// 创建一个文件输出流
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
// 将文件输出流包装成可写基本类型的流
java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);
// 写入对列中图形的个数
dos.writeInt(shapes.getSize());
// 读取队列
for (int i = 0; i < shapes.getSize(); i++) {
// 取出一种形状
Shape shape = shapes.get(i);
System.out.println(shape);
String type = shape.type;
System.out.println(type);
dos.writeInt(type.getBytes().length);
dos.write(type.getBytes());
if (type.equals(" 直线 ")) {
// 强制转型成直线类
Line line = (Line) shape;
Color color = line.color;
int rgb = color.getRGB();
// 写直线形状的数据
int x1 = line.x1;
int y1 = line.y1;
int x2 = line.x2;
int y2 = line.y2;
dos.writeInt(rgb);
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
}
if (type.equals(" 矩形 ")) {
Rect rect = (Rect) shape;
Color color = rect.color;
int rgb = color.getRGB();
// 写出举行形状的数据
int x1 = rect.x1;
int y1 = rect.y1;
int x2 = rect.x2;
int y2 = rect.y2;
dos.writeInt(rgb);
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
}
}
dos.flush();
fos.close();
System.out.println(" 保存 ");
} catch (Exception ef) {
ef.printStackTrace();
}
return false;
}
/**
* 定义一个打开保存图片的方法
* @param path
* 要打开文件的路径
* @return
*/
public Arrayexe<Shape> openPic(String path) {
// 创建一个队列用来保存从文件中读取的数据
Arrayexe<Shape> shapes = new Arrayexe<Shape>();
try {
// 创建一个文件对象的输入流
java.io.FileInputStream fis = new java.io.FileInputStream(path);
// 将文件输入流包装成可读几本类型流
java.io.DataInputStream dis = new java.io.DataInputStream(fis);
// 先去长度,及总共的形状的个数
int len = dis.readInt();
// 根据读取到的长度,我们就知道需要循环多少次才能将所有的形状读完
for (int i = 0; i < len; i++) {
int typeLen = dis.readInt();// 读类型长度
// 根据长度创建 byte 数组
byte[] tp = new byte[typeLen];
dis.read(tp);
String type = new String(tp);
int rgb = dis.readInt();
Color c = new Color(rgb);// 读取图形颜色
if (type.equals(" 直线 ")) {
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
Line line = new Line(c,x1,y1,x2,y2);
shapes.add(line);
} else if (type.equals(" 矩形 ")) {
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
Rect rect = new Rect(c,x1,y1,x2,y2);
shapes.add(rect);
}
}
System.out.println(" 打开 ");
fis.close();
} catch (Exception ef) {
ef.printStackTrace();
}
return shapes;
}
}
二、 在画板窗体上增加两个按钮:“保存”,“打开”
javax.swing.JButton save = new javax.swing.JButton(" 保存 ");
javax.swing.JButton open = new javax.swing.JButton(" 打开 ");
this.add(save);
this.add(open);
三、 在按钮上加上监听器;
save.addActionListener(listener);
save.setActionCommand(" 保存 ");
open.addActionListener(listener);
open.setActionCommand(" 打开 ");
四、 在监听器类中得到动作命令:
在动作命令点击“保存”和“打开”按钮时分别调用文件操作类中的 savefile 方法和 openpic 方法。
// 动作命令的方法体,实现点击按钮转换按钮功能的作用
public void actionPerformed(ActionEvent e) {
// 得到按钮的动作命令
String st = e.getActionCommand();
if (st.equals(" 颜色 ")) {
// 弹出一个颜色选择器
c = javax.swing.JColorChooser.showDialog(null, " 请选择颜色! ",
java.awt.Color.black);
}
if (st.equals(" 保存 ")) {
// 创建 File 对象
FileUtil fu = new FileUtil();
fu.saveFile(path, shapes);
}
if (st.equals(" 打开 ")) {
// 创建一个 FileUtil 对象
FileUtil fu = new FileUtil();
Anothertime.shapes = fu.openPic(path);
// 刷新是保存图片在窗体上显现
Anothertime at = new Anothertime();
at.paint(g);
}
else {
type = st;
}
所用到的技术分析:
文件输入输出流的应用,监听器的添加,与按钮功能的实现,方法的调用与参数的传递。
操作中遇到主要问题:
1 、原来制作的画板在 Shape 抽象类中由于没有定义 type 类型的变量,而在 Rect 和 Line 画图方法类中也没有 type 类型变量,只在监听器类中定义了这么一个变量,因此在文件保存操作中 String type = shape.type; 的调用就会出现空指针异常的产生;
2 、由于类中的继承同时由于在各类中相同涵义的变量、方法所用名称相同,导致在调用时混淆了方法与变量,导致程序出错。
画图板保存的拓展分析:
该画图板保存的路径是固定的,因此可以考虑用 Jfilechooser 实现路径的选择使自己的文件可以放到指定位置;美化界面;定义其他格式,从而可以用普通的图片查看器打开自己绘制的图片。