`
剑&箫
  • 浏览: 54588 次
  • 性别: 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 通过自定义的...

    烟草局考试计算机专业考试题.pdf

    Windows 附件自带的应用程序包括记事本、画图和写字板等。这些应用程序可以处理文字和图形,可以满足用户的基本需求。 Windows XP 操作系统自身携带的媒体播放器是 Windows Media Player。Windows Media Player 是...

    专升本计算机考试试题含答案(一级水平2).doc

    - 文件传输和文件访问在网络中含义不同,前者涉及数据交换,后者涉及数据存取。 7. 其他计算机知识: - Excel 的 COUNT 函数计算非空单元格的数量,A1:A4 包含 3 个非空单元格。 - 行号以阿拉伯数字排列。 - ...

    2012年计算机统考应用基础模拟试卷5.pdf

    1. 计算机硬件与规模分类:个人计算机(PC)属于微型计算机,其主要组成部分包括CPU(中央处理器)、RAM(随机存取存储器)和ROM(只读存储器)。序列机的推出是为了适应硬件不断更新的需求,保持软件的稳定性。 2....

    2011年9月计算机基础统考测试题(3).pdf

    24. 无法通过双击桌面上的“画图”图标启动。 25. 单击任务栏按钮可以切换活动窗口。 26. 汉字输入法状态栏显示在屏幕底部。 27. 终止PowerPoint幻灯片放映的快捷键是“Esc”。 28. “幻灯片2/7”表示当前显示第二张...

    2021-2022计算机二级等级考试试题及答案No.14387.docx

    1. PrintScreen键:这个键用于将当前屏幕的图像复制到剪贴板,以便用户可以粘贴到其他应用程序如画图或Word中。 2. 中央处理器(CPU):CPU是计算机系统的核心,负责执行指令和控制硬件操作。 3. Connection对象...

    中职计算机应用基础期中试卷.docx

    10. **内存类型**:RAM(随机存取存储器)保存的数据在关机后会消失,而ROM(只读存储器)中的数据则不会。 11. **网络媒体格式**:.rm和.mp3是互联网上流行的音频和视频压缩格式。 12. **计算机硬件**:现代...

    计算机基础知识试题大全.docx

    RAM(随机存取存储器)是临时存储数据的,断电后数据会丢失,用于运行时的程序和数据。 5. **CD-ROM**:CD-ROM是只读光盘,用于存储大量数据,不可写入或修改数据。 6. **字处理软件**:常见的字处理软件包括...

    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...

    《计算机应用基础》1-6次作业.pdf

    RAM(随机存取存储器)在断电后会丢失数据。PowerPoint中可以合并和拆分单元格。人事管理程序属于应用软件。选定对象并设置“飞入”效果,该对象将在放映时呈现飞入动画。个人计算机必备的外部设备是显示器和键盘。...

    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...

Global site tag (gtag.js) - Google Analytics