基础数据流与对象流分别保存对象
一:前几天在考虑如何使用基础数据流来保存画图板中的数据; 分析: 1,截取图片之后根据图片的大小的创建二维数组,将颜色点保存在数组二维数组中; 2,在paint()方法中将保存在二维数组中的颜色点遍历出来,并绘制 3,如何将绘制的图形保存到文件中 保存; 创建文件输出流:FileOutputStream fos = new FileOutputStream(file); 创建基础数据流:DataOutputStream dos = new DataOutputStream(fos); 再判断监听器中是否存在 if(lis !=null){ int colors[][] = lis.colors; 再判断是否有颜色 if(colors !=null){ dos.wirteInt(lis.colors.lenght); dos.wirteInt(lis.colors[0].lenght); for (int i = 0; i < lis.colors.length; i++) { for (int j = 0; j < lis.colors[i].length; j++) { //将创建出来的颜色保存到创建的二维数组中 int color = lis.colors[i][j]; dos.wirteInt(color); } } } } 打开: FileInputStream fis = new FileInputStream(file); DataInputStream dis = new DataInputStream(fis); // 读取高度和t宽度 int height = dis.readInt(); int width = dis.readInt(); // 定义数组来存放读取的数据 lis.colors = new int[height][width]; for (int i = 0; i < lis.colors.length; i++) { for (int j = 0; j < lis.colors[i].length; j++) { lis.colors[i][j] = dis.readInt(); } } }} 文件的保存与打开 和将截取的图片保存与paint 二者的写法相似
代码如下:
package com.iteye.com; /** *界面的主类,监听器.文件 */ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import javax.swing.ButtonGroup; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JRadioButton; /** * 画图板的界面类 * * @author * */ public class DrawUI extends JFrame { String path = "F:\\abc\\a.img"; JPanel center; // 单选按钮组 ButtonGroup group = new ButtonGroup(); DrawListener lis; public static void main(String args[]) { DrawUI du = new DrawUI(); du.initUI(); } /** * 初始化窗体的方法 */ public void initUI() { this.setTitle("画图板"); this.setSize(600, 400); // 设置点击关闭按钮的时候退出程序 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置窗体的布局为边框布局 BorderLayout layout = new BorderLayout(); this.setLayout(layout); JMenuBar bar = createJMenuBar(); this.setJMenuBar(bar); JPanel left = this.cerateLeft(); JPanel center = this.createCenter(); JPanel bottom = this.createBottom(); this.add(left, BorderLayout.WEST); this.add(center, BorderLayout.CENTER); this.add(bottom, BorderLayout.SOUTH); this.setVisible(true); // 创建监听器对象 lis = new DrawListener(group); // 给center加上监听器 center.addMouseListener(lis); } /** * 创建菜单条的方法 * * @return */ public JMenuBar createJMenuBar() { JMenuBar bar = new JMenuBar(); JMenu menu = new JMenu("文件"); JMenuItem saveItem = new JMenuItem("保存"); saveItem.setActionCommand("save"); JMenuItem openItem = new JMenuItem("打开"); openItem.setActionCommand("open"); menu.add(saveItem); menu.add(openItem); bar.add(menu); // 给菜单选项添加动作监听器 ActionListener alis = new MyListener(); saveItem.addActionListener(alis); openItem.addActionListener(alis); return bar; } public JPanel cerateLeft() { // 创建三个JPanel JPanel left = new JPanel(); // 设置背景颜色 left.setBackground(new Color(215, 215, 215)); // 设置大小 Dimension dim = new Dimension(80, 100); left.setPreferredSize(dim); // 在左边添加形状选择按钮 String[] items = { "直线", "矩形", "椭圆" }; String[] commands = { "line", "rect", "oval" }; for (int i = 0; i < items.length; i++) { JRadioButton btn = new JRadioButton(items[i]); // 设置按钮的动作命令 btn.setActionCommand(commands[i]); // 分为同一个组 group.add(btn); if (i == 0) {// 设置第一个被选中 btn.setSelected(true); } left.add(btn); } return left; } public JPanel createCenter() { // center需要在改变的时候重新绘制数据,所以要创建MyPanel类的对象 center = new MyPanel(); center.setBackground(Color.WHITE); return center; } public JPanel createBottom() { JPanel bottom = new JPanel(); bottom.setBackground(new Color(215, 215, 215)); bottom.setPreferredSize(new Dimension(100, 80)); return bottom; } // 内部类 class MyPanel extends JPanel { // 重写绘制JPanel的方法 // JPanel发生改变的时候,此方法会自动调用 // 在这个时候可以将需要的数据重新绘制在JPanel上 public void paint(Graphics g) { super.paint(g); // 如果监听器存在,就获得保存图像数据的二维数组 if (lis != null) { int[][] colors = lis.colors; // 如果二维数组存在,证明至少绘制过一次图像 if (colors != null) { // 遍历二维数组 for (int i = 0; i < colors.length; i++) { for (int j = 0; j < colors[i].length; j++) { // 得到点的颜色 Color c = new Color(colors[i][j]); // 绘制一个点 g.setColor(c); g.drawLine(j, i, j, i); } } } } } } // 动作监听器 class MyListener implements ActionListener { public void actionPerformed(ActionEvent e) { // 获得动作命令 String command = e.getActionCommand(); System.out.println(command); if (command.equals("save")) { try { // 将内存中的形状队列保存到文件中 File file = new File(path); FileOutputStream fos = new FileOutputStream(file); DataOutputStream dos = new DataOutputStream(fos); if (lis != null) { int[][] colors = lis.colors; // 如果二维数组存在,证明至少绘制过一次图像 if (colors != null) { // 先写出二维数组的大小 dos.writeInt(lis.colors.length);// 高度 dos.writeInt(lis.colors[0].length);// 宽度 for (int i = 0; i < lis.colors.length; i++) { for (int j = 0; j < lis.colors[i].length; j++) { int color = lis.colors[i][j]; dos.writeInt(color); } } dos.flush(); fos.close(); } } } catch (Exception ef) { ef.printStackTrace(); } } if (command.equals("open")) { try { // 建立文件输入流 File file = new File(path); FileInputStream fis = new FileInputStream(file); DataInputStream dis = new DataInputStream(fis); // 读取高度和t宽度 int height = dis.readInt(); int width = dis.readInt(); // 定义数组来存放读取的数据 lis.colors = new int[height][width]; for (int i = 0; i < lis.colors.length; i++) { for (int j = 0; j < lis.colors[i].length; j++) { lis.colors[i][j] = dis.readInt(); } } fis.close(); //刷新界面,将数据绘制在界面上 center.repaint(); } catch (Exception ef) { ef.printStackTrace(); } } } } }
package com.iteye.com; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import javax.swing.ButtonGroup; import javax.swing.JPanel; /** * 画图板的监听器,继承了鼠标适配器抽象类 * 鼠标适配器抽象类实现了MouseLIstener,MouseMotionListener,MouseWheelListener 只需要重写要是用到的方法 * * @autho */ public class DrawListener extends MouseAdapter { private int x1, y1, x2, y2; private Color c = Color.RED; private Graphics g; private ButtonGroup group; private String command;// 动作命令,作为要绘制的形状类型 line直线 rect矩形 oval椭圆 JPanel center; int[][] colors; public DrawListener(ButtonGroup group) { this.group = group; } /** * MouseEvent :鼠标事件对象,可以得到触发事件的对象 */ public void mousePressed(MouseEvent e) { // 获得事件源对象:鼠标在那个组件上触发事件,这个对象必须要是添加了监听器的 // 在本例中是给Center添加的监听器,事件源一定是Center center = (JPanel) e.getSource(); // 只需要绘制在center上,所以需要从Center上取画布 // 获得center组件在屏幕上占据的区域 g = center.getGraphics(); // 获得要绘制的形状 // 得到按钮组中被选中的按钮的动作命令 command = group.getSelection().getActionCommand(); x1 = e.getX(); y1 = e.getY(); } public void mouseReleased(MouseEvent e) { x2 = e.getX(); y2 = e.getY(); if (command.equals("line")) { // 画直线 g.drawLine(x1, y1, x2, y2); } else if (command.equals("rect")) { // 画矩形 g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2)); } else if (command.equals("oval")) { // 绘制椭圆 g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2)); } // 绘制完一个图形,就截取一次屏幕 try { Robot robot = new Robot(); // 定义要截取的矩形区域, // 由于要把center中的数据全部保存, // 所以矩形区域就是center在屏幕上占据的区域 // 获得center左上角的点相对于屏幕的坐标 Point point = center.getLocationOnScreen(); // 获得center的宽度和高度 Dimension dim = center.getSize(); Rectangle rect = new Rectangle(point, dim); // 调用截取屏幕的方法 BufferedImage img = robot.createScreenCapture(rect); // System.out.println("left-top:"+point.x+" "+point.y); // System.out.println("dimension:"+dim.width+" "+dim.height); // 根据图像大小定义一个二维数组,用来保存图像中的点 // 图像坐标和数组下标要注意区分 colors = new int[img.getHeight()][img.getWidth()]; // 每种颜色都是有ARGB四个子节组成,每种颜色都可以用int表示 for (int i = 0; i < colors.length; i++) { for (int j = 0; j < colors[i].length; j++) { // 将图像每个坐标点的颜色放到数组对应的下标位置 colors[i][j] = img.getRGB(j, i); } } } catch (Exception ef) { ef.printStackTrace(); } } }
二: 对象流保存(在JAVASE里面写过,就不再贴出来了) 分析 1,将绘制的图形的基本属性定义成一个抽象类,每个图形都去继承它 2,使用队列来保存绘制的图像 3,在paint方法中遍历队列,将遍历出来的队列个数绘制出来(此处是绘制,不是添加到队列中 很容易搞错的); 4,对象流的打开与保存 打开; 先读取个数; 遍历个数并转换成对象,再添加到队列中 保存: 先写图形的个数 遍历队列中的个数--->将个数写出去