画板数据保存成文件的两种方法小结

前面我学习了绘制画板以及画板的重绘,最近学习将画板数据保存成文件,与大家分享下。关于画板的保存有两种方式。先说说用队列来保存文件吧:首先需要将重绘时用来保存对象的队列按我们定义的文件格式写入文件:
/**
* 保存图形的方法
* @param path路径
* @param li队列
* @return 返回保存是否成功。
*/
public boolean SaveFile(String path,ListImpl li){
boolean state = false;
try{
//实例化输出流对象
OutputStream fis = new FileOutputStre(path);
DataOutputStream dos = new DataOutputStream(fis);
//写入队列的长度
dos.writeInt(li.size());
//循环
for(int i=0;i<li.size();i++){
Graph graph= (Graph)li.get(i);
//获取图形
byte item = graph.getItem();
//写入图形
dos.writeByte(item);
//写入坐标和宽高
int x1 = graph.getX1();
int y1 = graph.getY1();
int x2 = graph.getX2();
int y2 = graph.getY2();
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
//写入颜色
int r = graph.getColor().getRed();
int g = graph.getColor().getGreen();
int b = graph.getColor().getBlue();
dos.writeInt(r);
dos.writeInt(g); dos.writeInt(b);
}
dos.close();
os.close();
state = true;
}catch(IOException e){
e.printStackTrace();
}
return state;
}
文件的打开就是将数据从存储器中取出来,要注意的地方是我们是按照什么顺序写出去的,就按照相同的顺序读取进来,然后每次读取一个形状就将读取到的数据重新包装成对象,保存到一个队列去:
/**
* 打开图形方法
* @param path:路径
* @return:返回打开是否成功
*/
public boolean OpenFile(String path){
boolean state = false;
try{
//实例化输入流对象
InputStream fis = new FileInputStream(path);
DataInputStream dis = new DataInputStream(fis);
//读取图形总数
int size = dis.readInt();
//循环
for(int i=0;i<size;i++){
byte item = (byte) dis.readByte();
//读取坐标和宽高
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
//读取颜色
int r = dis.readInt();
int g = dis.readInt();
int b = dis.readInt();
Color color = new Color(r,g,b);
Graph graph = new Graph(item,color,x1,y1,x2,y2);
DrawListener.li.add(graph);
}
dis.close();
fis.close();
state = true;
}catch(IOException e){
e.printStackTrace();
}
return state;
}
}
这样保存和打开文件的基本代码就完成了,还需要在窗体上增加保存和打开两个按钮,然后加上一个ActionListener:
//使用匿名内部类方法来实现按钮的动作事件处理类
ActionListener al = new ActionListener(){
//动作事件的处理
public void actionPerformed(ActionEvent e){
//判断当前点击的按钮是否是Color
if(e.getActionCommand().equals("Color")){
color = JColorChooser.showDialog(null,"选择颜色",Color.RED);
System.out.println("Color:"+color);
}else if(e.getActionCommand().equals("Save")){
SaveOpen so = new SaveOpen();
//得到保存路径
boolean state = so.SaveFile("D:\\study0727\\draw", DrawListener.li);
System.out.println("保存成功!"+state);
}else if(e.getActionCommand().equals("Open")){
SaveOpen so = new SaveOpen();
//得到打开路径
boolean state = so.OpenFile("D:\\study0727\\draw");
.out.println("打开文件!"+state);
//调用重绘方法
up();

}else if(e.getActionCommand().equals("Line")){
item = 0;
System.out.println("你点击的按钮是Line");
}else if(e.getActionCommand().equals("Rect")){
item = 1;
System.out.println("你点击的按钮是Rect");
}else if(e.getActionCommand().equals("Oval")){
item = 2;
System.out.println("你点击的按钮是Oval");
}
}
};
到这里用队列保存画图板的文件就算完成了,当然这个文件格式是我们自己定义的,按照这种方式保存的图片用我们常用的图片查看器是打不开的,那是因为那些图片查看器不知道我们保存文件的格式。但用正版的BMP格式来保存文件还有问题,那就用山寨版的BMP来保存画板文件吧。与队列保存文件一样都需要读取文件和打开文件步骤。用输入流、输出流来完成。
/**
* 读取文件
* @param path
* @return
*/
public int[][] readFile(String path) {
try {
// 根据文件路径创建一个文件输入流
java.io.FileInputStream fis = new java.io.FileInputStream(path);
java.io.DataInputStream dis=new java.io.DataInputStream (fis);
dis.readInt();
// 根据字节数创建一个字节数组
int[][] colors=new int[width][height];
int t = dis.read();
while (t != -1) {// 如果没有到达文件末尾,就循环读取
for (int i = 0; i < width; i++) {
for (int j = 0; j <height ; j++) {
colors[i][j] = t;
// 继续读取下一个字节
t = dis.read();
}
}
}

// 关闭流
fis.close();
return colors;
} catch (Exception ef) {
ef.printStackTrace();
}
return null;
}
/**
* 保存到文件
*/
public void writeFile(String path,MyPanel panel) throws Exception{
// 创建一个文件输出流,如果文件不存在,会自动创建一个文件
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
java.io.DataOutputStream dos=new java.io.DataOutputStream(fos);
dos.writeInt(width);
dos.writeInt(height);
huaban.colors = new int[width][height];
for (int i = 0; i < width; i++) {
for (int j = 0; j <height ; j++) {
dos.write(huaban.colors[i][j]);
}
}
// 强制输出
dos.flush();
// 关闭流
fos.close();
}
同样需要在窗体上增加保存和打开两个按钮,然后给按钮加动作监听器
public void actionPerformed(ActionEvent e) {
// 得到按钮文字
String text = e.getActionCommand();
// 选择颜色
if (text.equals("选择颜色")) {
color = javax.swing.JColorChooser.showDialog(null, "请选择颜色",Color.black);
} else if(text.equals("保存")){
String path="D:\\画板保存.Bmp";
try {
writeFile(path,jp);
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.println("保存完毕");
}else if(text.equals("打开")){
String path="D:\\画板保存.Bmp";
readFile(path);
System.out.println("打开完毕");
}
str = text;
System.out.println(str);

}
此方法最不同于队列保存的地方是:定义保存图片的方法
public void savePic(MyPanel panel){
//确定需要保存的区域JPanel
//设置初始数组为空
huaban.colors=null;
// 得到panel左上角的点相对于屏幕的坐标
Point p = panel.getLocationOnScreen();
//得到JPanel左上角的坐标、宽度、高度
width = panel.getWidth();
height = panel.getHeight();
huaban.colors = new int[width][height];
//根据JPanel左上角的坐标、宽度、高度创建一个屏幕区域对象
java.awt.Rectangle rect = new java.awt.Rectangle(p.x, p.y,
panel.getWidth(), panel.getHeight());
try {

//创建一个机器人
robot = new java.awt.Robot();
} catch (Exception ef) {
ef.printStackTrace();
}
// 从屏幕上抓取一张图片
java.awt.image.BufferedImage img =
robot.createScreenCapture(rect);
//遍历数组
for (int i = 0; i < width; i++) {
for (int j = 0; j <height ; j++) {
//得到图像上每个坐标点RGB颜色,并将颜色对应的保存到数组中
huaban.colors[i][j] = img.getRGB(i, j);
}
}

}
[FLASH/AS1/2]简易涂鸦板(带本地保存功能与撤消上一步功能) 作者:古树悬叶 日期:2010-01-07 二类涂鸦板:一种是主流的通过保存鼠标轨迹的方式来保存涂鸦数据,既使用矢量的方式来保存,样例如闪吧的涂鸦程序;另一种是通过保存 BitmapData 颜色值的方式来保存,样例还没有找到比较像样的样例。 在《内置方法Array.shift 与自定义循环++的执行效率比较》一文中,我已经对 shift 方法与自定义的 ++ 方式分别作了比较。虽然自定义 ++ 的方式比shift方法要快,但事实它们二者的效率都很低。由于 SharedObject 类是无法直接保存 BitmapData 对象的,所以只能将 BitmapData 的所有位图像素的每一个像素取 ARGB 值后保存。一张位图按500像素 x 500像素算,自定义 ++ 需要3秒多,而 shit 方法脚本超时。所以通过 BitmapData 的颜色方式来保存只能保存较小的位图。所以通过鼠标轨迹的方式保存涂鸦了主流。 此涂鸦板在涂鸦之后会自动将涂鸦保存在本地,并且可以撤消上一步操作。涂鸦画线功能我是直接从FLASH帮助文件中考贝出来的,我在涂鸦功能的基础上添加了本地保存和撤消的功能。(代码可以扩展自定义线条粗细,自定义线条颜色,透明度等等。还可以添加新的数据用来记录被撤消的步聚,这样不旦可以撤消还有了重做功能。甚至还可以在 tempArray.push 添加新的数组,同时保存不同线条粗细、颜色、透明度的涂鸦,做一个类似画板的程序。) 謾軻(Manction) http://manction.51.com 2010.01.07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值