数据输入流和对象流分别保存画图板的图形
程序员文章站
2022-07-13 14:50:15
...
基础数据流与对象流分别保存对象
一:前几天在考虑如何使用基础数据流来保存画图板中的数据;
分析:
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,对象流的打开与保存
打开;
先读取个数;
遍历个数并转换成对象,再添加到队列中
保存:
先写图形的个数
遍历队列中的个数--->将个数写出去