`
剑&箫
  • 浏览: 53057 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

画图板数据的存取

    博客分类:
  • Java
阅读更多
前段时间作了个简单的画图板,能够画直线,矩形,椭圆,三角形四种颜色以及能够选择各种形状的颜色。首先来看一下此画图板的截图,如下图:




现在主要总结将此画图板上的数据保存为文件,这里的保存只能用自己的画图板打开,不能用其他图片查看器打开。
在Java中DataInputStream和DataOutputStream这两种流主要用来读写指定的数据类型,比如要读取一个8字节的Long型数据,读取一个4字节的int型数据,用这两种流非常方便。有了前面对流的使用经验和总结,就很容易掌握这两种流的使用。但是首先还需要来看在API文档中这两种流的构造方法和其他方法摘要。这两种流都只有一个构造方法,分别是DataInputStream(InputStream in)和DataOutputStream(OutputStream out)。了解了这两个流之后,就可以对画图板数据的保存和读取了。首先先介绍用自定义队列对画图板数据的保存,由前面对流的使用的经验,先来创建一个方法writeFile()对画图板数据的保存,再向该方法中传入要保存的文件路径和形状队列两个参数。再创建文件输出流和数据输出流对象分别为:java.io.FileOutputStream fos = new java.io.FileOutputStream(path); java.io.DataOutputStream  dos = new  java.io.DataOutputStream(fos);然后再用writeInt(int v)方法写出队列的长度,接着遍历队列,判断队列中每个元素的形状类型,在得到各形状类型的属性,最后分别写出各形状的属性数据。具体代码如下:

/**
* 将图片保存到指定文件
* @param path:文件的指定路径
* @param list:形状队列
*/
public void writeFile(String path,ListTest<Shape> list){

try{
//创建输出流对象
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
//创建数据输出流对象
java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);

//写出队列的长度
dos.writeInt(list.size());

//遍历队列
for (int i=0;i<list.size();i++){
//取出队列的元素
Shape sh = list.get(i);

byte type = sh.type;
//写出形状的类型
dos.writeByte(type);

if (type==0){//如果是直线
//强制转型
Line line = (Line)sh;
//获得直线的属性
int x1 = line.x1;
int y1 = line.y1;
int x2 = line.x2;
int y2 = line.y2;
int color = line.color.getRGB();

//写出直线的属性
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
dos.writeInt(color);

}else if (type==1){//如果是矩形
Rect rect = (Rect)sh;
//获得矩形的属性
int x1 = rect.x1;
int y1 = rect.y1;
int x2 = rect.x2;
int y2 = rect.y2;
int color = rect.color.getRGB();

//写出矩形的属性
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
dos.writeInt(color);


}else if (type==2){//如果是椭圆
Oval oval = (Oval)sh;
//获得椭圆的属性
int x1 = oval.x1;
int y1 = oval.y1;
int x2 = oval.x2;
int y2 = oval.y2;
int color = oval.color.getRGB();

//写出椭圆的属性
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
dos.writeInt(color);


}else if (type==3){//如果是三角形
Triangle tg = (Triangle)sh;
//获得三角形的属性
int x1 = tg.x1;
int y1 = tg.y1;
int x2 = tg.x2;
int y2 = tg.y2;
int color = tg.color.getRGB();

//写出三角形的属性
dos.writeInt(x1);
dos.writeInt(y1);
dos.writeInt(x2);
dos.writeInt(y2);
dos.writeInt(color);


}

}

//强制输出
dos.flush();
//关闭输出流
fos.close();

}catch(Exception et){
et.printStackTrace();
}

}

将保存的数据读取是上面保存数据的一个逆过程,首先先定义一个方法readFile(),传入要读取文件的路径参数,该方法的返回值是一个自定义队列。首先要实例化一个自定义队列:ListTest<Shape> list = new ListTest<Shape>();然后和上面一样创建文件输入流和数据输入流对象,分别为:java.io.FileInputStream fis  = new java.io.FileInputStream(path);和java.io.DataInputStream  dis = new  java.io.DataInputStream(fis);再根据上面写出的顺序,上面是怎么写出的,这里就要怎么读取,最后要创建各种形状的对象加入到自定义队列中。具体代码如下所示:
/**
* 将制定 的文件读取到内存中
* @param path:指定文件路径
* @return:返回形状队列
*/
public ListTest<Shape> readFile(String path){
//实例化一个队列
ListTest<Shape> list = new ListTest<Shape>();

try{
//创建输入流对象
java.io.FileInputStream fis  = new java.io.FileInputStream(path);
//创建数据输入流对象
java.io.DataInputStream dis = new java.io.DataInputStream(fis);

//读入一个Int,作为队列的长度
int len = dis.readInt();

//遍历数组
for (int i=0;i<len;i++){
//读入一个byte
byte type = dis.readByte();

if (type==0){//如果是直线
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
Color color =new Color(dis.readInt());

//创建直线对象
Line line = new Line(x1,y1,x2,y2,color);
//将直线加入到队列中
list.add(line);

}else if (type==1){//如果是矩形
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
Color color =new Color(dis.readInt());

//创建直线对象
Rect rect = new Rect(x1,y1,x2,y2,color);
//将直线加入到队列中
list.add(rect);

}else if (type==2){//如果是椭圆
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
Color color =new Color(dis.readInt());

//创建直线对象
Oval oval = new Oval(x1,y1,x2,y2,color);
//将直线加入到队列中
list.add(oval);

}else if (type==3){
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
Color color =new Color(dis.readInt());

//创建直线对象
Triangle tg = new Triangle(x1,y1,x2,y2,color);
//将直线加入到队列中
list.add(tg);
}

}

//关闭输入流
fis.close();

}catch(Exception et){
et.printStackTrace();
}


return list;
}

接下来要总结一种山寨BMP保存画图板的数据。这种保存方式的原理是将画图的区域看成是一个一个的像素点,根据画得图形的颜色与背景颜色的值不同分别画出各点形成画得形状图形。首先要定义一个类,该类的作用就是要获取所保存区域的存有各点颜色值的二维颜色数组。思路是获取要保存的区域,这里是Jpanel区域,然后得到Jpanel左上角相对于屏幕的坐标,根据左上角的坐标创建一个屏幕区域对象,再创建一个Robot类的对象,从屏幕截取图像既可以得到图像上每个坐标点的颜色值,最后创建一个二维数组将颜色值对应的保存到数组中。具体代码如下所示:
/**
* 山寨BMP保存
*
* @author Administrator
*
*/
public class Save4Bit {

static int width;
static int height;
static int[][] colors;// 用来保存每一个像素点颜色的数组
static java.awt.Robot robot;

public static void savePic(JPanel panel) {

try {
robot = new java.awt.Robot();
} catch (Exception ef) {
ef.printStackTrace();
}
//得到JPanel的宽度与长度
width = panel.getWidth();
height = panel.getHeight();
colors = new int[height][width];

// 得到panel左上角的点相对于屏幕的坐标
Point p = panel.getLocationOnScreen();

java.awt.Rectangle rect = new java.awt.Rectangle(p.x, p.y,
panel.getWidth(), panel.getHeight());
// 从屏幕上抓取一张图片
java.awt.image.BufferedImage img = robot.createScreenCapture(rect);

for (int i = 0; i < colors.length; i++) {
for (int j = 0; j < colors[i].length; j++) {
colors[i][j] = img.getRGB(i, j);
}
}

}
}
这样作之后,画图板的重绘就与上面那种方式不同了,具体的请比较两种重绘的代码:
第一种保存方式的重绘代码:
//当窗体改变时,该方法自动调用
public class MyPanel extends JPanel{
public void paint(java.awt.Graphics g){
//调用父类的方法
super.paint(g);

//遍历队列的元素
for (int i=0;i<lines.size();i++){
Shape sh = lines.get(i);
    sh.draw(g);
}
}

}
第二种保存重绘的代码:
//当窗体改变时,该方法自动调用
public class DrawPanel extends JPanel{
public void paint(java.awt.Graphics g){
//调用父类的方法
super.paint(g);
if (Save4Bit.colors!=null){
//遍历colors数组,取出它的元素,即点的颜色再重新画
for (int i=0;i<Save4Bit.colors.length;i++){
for (int j=0;j<Save4Bit.colors[i].length;j++){

int rgb = Save4Bit.colors[i][j];
if (panel.getBackground().getRGB()!=rgb){
Color color=new Color(rgb);
g.setColor(color);
g.drawLine(i, j, i, j);

}

}
}
}

}

}

获取颜色数组之后就要对数组元素数据的读取和保存了,方法与上面差不多,具体如下:
import javax.swing.JPanel;
/**
* 山寨BMP保存画板
* @author lenovo
*
*/
public class SaveFile {
JPanel panel = new JPanel();

//构造方法
public SaveFile(JPanel panel){
this.panel = panel;
}
/**
* 将数据保存到指定文件
* 1.创建输出流和数据输出流
* 2.首先要得到颜色数组
* 3.写出数组的两个长度
* 4.最后写出数组的每个元素的数据
* @param path:指定文件的路径
* @param colors:像素点颜色的数组
*/
public void writeFile(String path,int[][] colors){
Save4Bit.savePic(panel);
try{
//创建输出流对象
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);

java.io.BufferedOutputStream bos = new java.io.BufferedOutputStream(fos);
//创建数据输出流对象
java.io.DataOutputStream dos = new java.io.DataOutputStream(bos);

//写出数组的两个长度
dos.writeInt(Save4Bit.height);
dos.writeInt(Save4Bit.width);

//遍历数组写出数组各元素的数据
for (int i=0;i<colors.length;i++){
for (int j=0;j<colors[i].length;j++){
dos.writeInt(colors[i][j]);
}
}

dos.flush();
fos.close();
}catch(Exception et){
et.printStackTrace();
}

}
/**
* 将指定文件读到内存中
* 1.创建一个二维数组
* 2.创建输入流和数据输入流
* 3.先读取两个Int作为二维数组的长度
* 4.再读取数据存到数组中
* @param path:指定文件的路径
* @return:返回颜色数组
*/
public int[][] readFile(String path){

try{
//创建输入流对象
java.io.FileInputStream fis = new java.io.FileInputStream(path);

java.io.BufferedInputStream bis = new java.io.BufferedInputStream(fis);

//创建数据输入流对象
java.io.DataInputStream dis = new java.io.DataInputStream(bis);

//读取数组的两个长度
int height = dis.readInt();
int width = dis.readInt();

//创建一个二维数组
int[][] colors = new int[height][width];

for (int i=0;i<height;i++){
for (int j=0;j<width;j++){
colors[i][j]=dis.readInt();
}
}

fis.close();
return colors;

}catch(Exception et){
et.printStackTrace();
}

return null;

}

}
这样在保存和打开两个按钮上加上监听器,然后在分别创建对象调用相应的方法就可以对画图板数据的保存和读取了。




  • 大小: 15 KB
1
13
分享到:
评论

相关推荐

    android初学者入门项目

    31、SharedPreference 简单的key-value数据存取 32、SQLiteDatabase 安卓客户端的嵌入式数据库 33、GestureDetector + ViewFlipper实现翻页效果 34、GestureLiberay 自定义手势 35、GestureLiberay 通过自定义的...

    android开发demo集合

    31、SharedPreference 简单的key-value数据存取 32、SQLiteDatabase 安卓客户端的嵌入式数据库 33、GestureDetector + ViewFlipper实现翻页效果 34、GestureLiberay 自定义手势 35、GestureLiberay 通过自定义的...

    C#程序开发范例宝典(第2版).part13

    实例168 简单画图程序 236 实例169 看图工具 239 实例170 文字保存为图片 240 实例171 捕获屏幕 241 4.10 图像应用 243 实例172 随机更换壁纸程序 243 实例173 屏幕保护 244 实例174 模拟石英钟 247 实例175...

    C#程序开发范例宝典(第2版).part08

    实例168 简单画图程序 236 实例169 看图工具 239 实例170 文字保存为图片 240 实例171 捕获屏幕 241 4.10 图像应用 243 实例172 随机更换壁纸程序 243 实例173 屏幕保护 244 实例174 模拟石英钟 247 实例175...

    C#程序开发范例宝典(第2版).part02

    实例168 简单画图程序 236 实例169 看图工具 239 实例170 文字保存为图片 240 实例171 捕获屏幕 241 4.10 图像应用 243 实例172 随机更换壁纸程序 243 实例173 屏幕保护 244 实例174 模拟石英钟 247 实例175...

    C#程序开发范例宝典(第2版).part12

    实例168 简单画图程序 236 实例169 看图工具 239 实例170 文字保存为图片 240 实例171 捕获屏幕 241 4.10 图像应用 243 实例172 随机更换壁纸程序 243 实例173 屏幕保护 244 实例174 模拟石英钟 247 实例175...

    C#.net_经典编程例子400个

    299 7.6 系统监控 299 实例211 检测系统启动模式 300 实例212 内存使用状态监控 301 实例213 监视剪贴板内容 302 7.7 系统软件信息 303 实例214 获取用户名 303 实例215 获取系统...

    计算机应用基础19春在线作业21.txt

    以上的说法都不对 正确答案:C 16."画图"程序在Windows 98的( ) A."附件"程序组中 B."安装"程序组中 C."计划任务"程序组中 D."系统工具"程序组中 正确答案:A 17.以下( )不是Excel 2000的功能。 A.幻灯片制作 B....

    Delphi开发范例宝典目录

    实例247 怎样存取注册表信息 318 实例248 注册表保存注册信息 319 实例249 禁止修改显示属性 321 实例250 列出注册表指定项下的全部键值 322 7.2 系统设置 323 实例251 隐藏、显示桌面图标 323 实例252...

    会计理论考试题

    19.软盘插入软盘驱动器后,驱动器的读写就通过读写窗口存取信息。( Y ) 20.计算机的常用输入设备有打印机和键盘。( N ) 第二套 选择题 1.PC机中 Intel8088、80286、80386、80486,PemiumPⅡ、PⅢ是指_D_的不同...

Global site tag (gtag.js) - Google Analytics