画图板:从画图到重绘到保存

 

上一篇博文已经具体的构建了画图板的整个框架   这里就具体的说明一下功能的实现问题

一、功能实现

1.简单的画图形

2.重绘:窗体最小化之后 打开窗体 画面不消失

3.保存文件: 把绘制出来的图片放在硬盘里 

二、难点分析

三、错误点集合



1.简单的画图形
画图形分为三步:
第一步:取画布
// 给他drawpanel获取画布
java.awt.Graphics g = drawpanel.getGraphics();
 第二步:取颜色 取图形
g.setColor(Color.LIGHT_GRAY);
 第三步:绘制图形
g.drawLine(x1, y1, x2, y2);
 

2.重绘:窗体最小化之后 打开窗体 画面不消失
介绍两种方法:
第一种:每个画出的图形用队列保存 重绘时只需遍历队列重画一下
建立队列  每次取到的sh都加到队列里

	// 定义一个队列用来存放形状对象~
		MyQueue<Shape> shapes;
	//建立一个Shape类型的对象把他设置为null
		Shape sh = null; 
		//将图形加入队列
		shapes.add(sh);
		//把图形画出来
		sh.draw(g);
 新建一个MyPanel类因为画布是在drawpanel上面取的
遍历形状队列 绘制出图形

			class MyPanel extends JPanel {

		/**
		 * 重写JPanel中用来绘制窗体的方法
		 */
		public void paint(Graphics g) {
			// 调用父类的方法来正确的绘制窗体
			super.paint(g);
			System.out.println("绘制了");
			// 遍历形状队列
			for (int i = 0; i < shapes.size(); i++) {
				// 取出形状
				Shape sh = shapes.get(i);
				// 绘制
				sh.draw(g);
			}
		}

	}
 
第二种方法:捕捉屏幕方法
因为drawpanel是由屏幕上的像素点组成的 
有不同的颜色是因为像素点各点存的颜色不一样,屏幕可以抽象看做一个二维数组 
所以只需要取到二维数组里每点的颜色即可 

核心是
// 创建Rectangle对象
Rectangle rec = new Rectangle(point, drawDim);
// 捕捉drawpanel上的像素图像
BufferedImage bimg = rb.createScreenCapture(rec);


// 建立一个robot对象
		try {
			Robot rb = new Robot();
			// 获取drawpanel左上角的点~
			Point point = drawpanel.getLocationOnScreen();
			// 获取drawpanel的dimension
			int width = drawpanel.getWidth();
			int height = drawpanel.getHeight();
			java.awt.Dimension drawDim = new java.awt.Dimension(width, height);
			// 创建Rectangle对象
			Rectangle rec = new Rectangle(point, drawDim);
			// 捕捉drawpanel上的像素图像
			BufferedImage bimg = rb.createScreenCapture(rec);
			// 现在要找图像上的像素点用一个二维数组来储存每个点的像素
			// 为存放屏幕上各点的颜色设置一个二维数组array
			Array.pointArray = new int[height][width];
			for (int i = 0; i < Array.pointArray.length; i++)
				for (int j = 0; j < Array.pointArray[i].length; j++) {
					// x是像素的x坐标 j是列 x = 1 为第一列~getRGB传入的应该是x y
					Array.pointArray[i][j] = bimg.getRGB(j, i);
				}
 

3.保存文件: 把绘制出来的图片放在硬盘里 
首先 在frame上设置按钮 通过监听器跟文件io流连接
			//加菜单项
			final javax.swing.JMenuItem item1 = new javax.swing.JMenuItem("保存");
			final javax.swing.JMenuItem item2 = new javax.swing.JMenuItem("打开");
			
			
			//加动作命令
			item1.setActionCommand("save");
			item2.setActionCommand("open");


			//建立匿名内部类 并
			ActionListener alis = new ActionListener(){

				public void actionPerformed(ActionEvent e) {
					//给item1和item2设置命令
					String command1 = item1.getActionCommand();
					String command2 = item2.getActionCommand();
					
					if(command1.equals("save")){
						
						//把图片保存成文件
						FileUtil.saveFile("G:\\蓝杰\\first.bmp");
						
					}
					if(command2.equals("open")){
						
						//把ispaint设置为true
						DrawListener.isPaint = true;
						
						//把文件从硬盘读取出来
						int[][] readData =FileUtil.readFile("G:\\蓝杰\\first.bmp");
						DrawListener.Point_Array = readData;
						
						//DrawListener.POINT_ARRAY = readData; 
						System.out.println(readData);
						
						// 刷新drawPanel
						drawpanel.updateUI();
					
					}else{
						System.out.println("出错了!!");
					}
					
				}
				
			};
			
			item1.addActionListener(alis);
			item2.addActionListener(alis);
 
然后:创建保存文件的方法

	/**
	 * 保存文件的方法
	 * @param path 要保存到的路径
	 */
	public static void saveFile(String path){
	
		try{
			//创建文件输出流
			java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
			//把他包装成数据流
			java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);
			
			//首先写入图片的高度和宽度
			dos.writeInt(DrawListener.Point_Array.length);
			dos.writeInt(DrawListener.Point_Array[0].length);
			
			//遍历颜色数组把颜色点都写入文件
			for(int i =0;i<DrawListener.Point_Array.length;i++)
				for(int j = 0;j<DrawListener.Point_Array[i].length;i++){
					
					//把颜色数组的内容写入文件
					dos.writeInt(DrawListener.Point_Array[i][j]);
				}
			
			//把数据流强制输出 文件流关闭	
			dos.flush();
			fos.close();
			
		}catch(Exception e){
			e.printStackTrace();
		}

	}
 
创建读取文件的方法

	/**
	 * 读文件 从硬盘到内存
 	 * @param path 要读入的文件路径
 	 */
	public static int[][] readFile(String path){
		
		
			try{
			//创建文件输入流
			java.io.FileInputStream fis = new java.io.FileInputStream(path);
			//把他包装成数据流
			java.io.DataInputStream dis = new java.io.DataInputStream(fis);
			
			//先读出数组的宽和高 放入新的二维数组里~
			int height = dis.readInt();
			int width = dis.readInt();
			
			//根据宽和高创建一个新的二维数组
			int[][] array = new int[height][width];
			
			//读取颜色把颜色放在新的二维数组里
			for(int i=0;i<height;i++)
				for(int j = 0;j<width;j++){
					array[i][j] = dis.readInt();
				}
			
			//只需要关闭输入流即可
			fis.close();
			return array;
			
			}catch(Exception e){
				e.printStackTrace();
			}
			
			return null;
	}

}
	
 
二、难点分析
1.捕捉屏幕方法中取到二维数组里每点的颜色
这里用了Color()的一种没用过的构造方法
就是 int值表示一个颜色  因为我们要把颜色放进二维数组
所以二维数组里的颜色只能有一个值 就是int
首先从捕捉drawpanel上的像素图像这个函数开始
BufferedImage bimg = rb.createScreenCapture(rec);
需要一个Rectangle 
创立Rectangle需要point和drawDim
所以就构造point和drawDim
BufferedImage有一个getRGB的方法  正好可以把它的int值放进颜色数组里 
这样就实现了捕捉屏幕(详细代码见 “二、重绘”)


2.关于记录颜色数组是放在接口还是类中的问题
开始时我把 Point_Array放入接口中 但接口中的数组大小不能发生改变 

而实际操作中 
在读取文件的函数里 获取的数组高度和宽度是放在新建的数组里

			//根据宽和高创建一个新的二维数组
			int[][] array = new int[height][width];
			
			//读取颜色把颜色放在新的二维数组里
			for(int i=0;i<height;i++)
				for(int j = 0;j<width;j++){
					array[i][j] = dis.readInt();
				}
 所以在listener里面要把新数组赋给Point_Array 结果出现了问题 

后来 就把Point_Array放进了drawlistener里就实现了


三、错误点集合
1. 这个readfile函数里 return有点小技巧
  在try里面 return 这个二维数组  在外面 return null
   说明 只有try了 才return
 
 

2.ispaint的问题
 出现整个drawpanel全部是黑色的情况
  错点分析:
 画布的设置颜色的方法传入的是颜色的一个int 值
 g.setColor(new Color(POINT_ARRAY[i][j]));
 这句代码 当画面上还没有绘制形状的时候POINT_ARRAY[i][j]都是零  而零表示黑色 
 所以一开始整个屏幕都是黑色
 
 所以我们在listener里设置了一个布尔型的变量ispaint来判断他是否已经有内容 
 public static boolean isPaint = false;  
 在mouserelease()函数的最后 当存入数据到数组中时  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值