关于Java截屏软件的开发收获

       这是第一次写技术博客,还是有点不知所措,前些时听人说技术这东西,不仅要自己会,还要能够说出来,让别人明白你在说什么。博主暂时是学生,本身还没什么实际企业项目开发经验,这篇文章权当学习经历的总结。


      好,言归正传。这个案例我会一步一步的来拆分讲解。

-----------------------------------------------------------我是分界线-------------------------------------------------------------


      涉及到的知识点:

      软件说明:可以进行局部的截屏。

      实现大概原理:

                        1.首先获取整个屏幕的图像内容,类似于全屏截图,但是不用去保存,而是将图像捕获到;

                        2.然后在捕获的图像上,再去截取所需的图像,保存下来。


      我们先完成第一步,先把这个软件的界面制作出来。如图下图:

                                                                                    

虽然界面很简单,但是简单易用可依赖性强,界面太复杂反而不容易使用。

       首先在main函数里面创建一个相框【JFrame】,接着创建桌布【JPanel】(我一直这么喊它= =什么东西都可以往上面放,这真的像桌布),就是整个界面,然后创建标签【JLabel】,将每个标签打上字,然后贴在桌布上,载将桌布嵌入相框。设置其界面大小等一类属性。代码如下:

<span style="font-size:14px;">		JFrame frame = new JFrame("截屏");
		JPanel a = new JPanel();
		JLabel b = new JLabel("Ctrl+Alt截图");
		JLabel c = new JLabel("Esc退出截屏界面");
		JLabel d = new JLabel("East_MrChiu制作");
		a.add(b);
		a.add(c);
		a.add(d);
		frame.add(a);
		frame.setSize(140, 110);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                frame.setResizable(false);//窗体大小不可变 
</span>
     

       这样我们得到了一个软件界面。接下来,我们要实现捕获全屏的图像,将其作为截屏的界面。接着我们定义按键Ctrl+Alt触发事件,那么需要创建一个监听管理器【KeyboardFocusManager】,然后在监听管理器中添加监听的进程,接着判断是否是否触发Ctrl+Alt按键。注意这里需要捕获异常。代码如下:

<span style="font-size:14px;">// 同时按下CTRL+ALT按键事件
		KeyboardFocusManager manager = KeyboardFocusManager
				.getCurrentKeyboardFocusManager();// 获得监听管理器
		manager.addKeyEventPostProcessor(new KeyEventPostProcessor() {// 添加事件监听进程
			@Override
			public boolean postProcessKeyEvent(KeyEvent e) {
				// 判断是否同时按下CTRL+ALT,若是,则进行截图
				if (e.isAltDown() && e.isControlDown()) {
					try {
						setVisible(false);//设置窗体不可见
						new ScreenWindow();//开始下一步的截屏处理
					} catch (Exception e2) {
						JOptionPane.showConfirmDialog(null, "出现意外错误!", "系统提示",
								JOptionPane.DEFAULT_OPTION,
								JOptionPane.ERROR_MESSAGE);
					}
				}
				return false;
			}
		});
</span>

接下来继续实现接触处理,完成
<span style="font-size:14px;">new ScreenWindow();</span>
这一步,我们创建一个ScreenWindow的类,继承JFrame,创建ScreenWindow函数。在进行下一步前,先回顾几个东西:


1.Dimension类封装单个对象中组件的宽度和高度(精确到整数)。该类与组件的某个属性关联。由 Component 类和 LayoutManager 接口定义的一些方法将返回Dimension对象。通常,widthheight 的值是非负整数。允许创建Dimension的构造方法不会阻止您为这些属性设置负值。如果 widthheight 的值为负,则由其他对象定义的一些方法的行为是不明确的。

2.ImageIcon:一个 Icon 接口的实现,它根据 Image 绘制 Icon。可使用 MediaTracker 预载根据 URL、文件名或字节数组创建的图像,以监视该图像的加载状态。

声明变量:

<span style="font-size:14px;">	public Dimension screenDims = null;// 屏幕大小
	public ImageIcon screenImageIcon = null;// 截取的图片
	public JLabel label = null;
	private boolean isDrag = false;
	private int x = 0;
	private int y = 0;
	private int xEnd = 0;
	private int yEnd = 0;
</span>
捕获全屏图像:
		// 捕获全屏
		screenDims = Toolkit.getDefaultToolkit().getScreenSize();// 获取整体屏幕大小内容
		screenImageIcon = new ImageIcon(<span style="color:#FF0000;">ScreenImage</span>.getScreenImage(0, 0,
				screenDims.width, screenDims.height));// 接受捕获的全屏图像
		label = new JLabel(screenImageIcon);// 将接受来的全屏图像放到标签上,以便接下来的操作
		label.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));// 设置在全屏截图图像上移动时的鼠标光标样式(这里设置成十字架样式)

其中的一个方法类ScreenImage需要定义:

	static// 截图
	class <span style="color:#FF0000;">ScreenImage</span> {
		public static Image getScreenImage(int i, int j, int width, int height)
				throws AWTException, InterruptedException {
			Robot robot = new Robot();
			Image screen = robot.createScreenCapture(
					new Rectangle(i, j, width, height)).getScaledInstance(
					width, height, Image.SCALE_SMOOTH);
			MediaTracker tracker = new MediaTracker(new Label());
			tracker.addImage(screen, 1);
			tracker.waitForID(0);
			return screen;
		}
	}

然后在捕获的全屏图像上进行分割截取所需局部图像,首先添加鼠标点击事件:分别是左键取消事件,按下事件,松开事件这三个事件。按下事件获取落点坐标,松开事件获取松点坐标,其中要松点坐标必须大于落点坐标,如果小于,则进行交换。当松开事件完成后,立刻弹出文件选择框,进行文件保存。具体先看代码:

// 添加鼠标点击事件
		label.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON3) {
					dispose();
				}
			}
			public void mousePressed(MouseEvent e) {
				x = e.getX();
				y = e.getY();
			}
			public void mouseReleased(MouseEvent e) {
				if (isDrag) {
					xEnd = e.getX();
					yEnd = e.getY();
					if (x > xEnd) {
						int temp = x;
						x = xEnd;
						xEnd = temp;
					}
					if (y > yEnd) {
						int temp = y;
						y = yEnd;
						yEnd = temp;
					}

					// 保存文件
					try {
						JFileChooser fileChooser = new JFileChooser();// 构造一个文件选择器
						// 设置主目录
						// 1.固件存储位置
						// fileChooser.setCurrentDirectory(new File("D:"));
						// 2.弹出保存文件的选择框
						fileChooser.setFileFilter(new FileFilter() {
							public boolean accept(File f) {
								return f.isDirectory() || f.getName().toLowerCase().endsWith(".jpg");
							}
							public String getDescription() {
								return "*.jpg";
							}
						});
						int result = fileChooser.showSaveDialog(null);
						if (result == JFileChooser.APPROVE_OPTION) {
							/*
							 * 获取局部截屏图像
							 */
							// 创建一个等大的图片框
							BufferedImage bufferedImage = new BufferedImage(
									xEnd - x, yEnd - x,
									BufferedImage.TYPE_INT_BGR);
							// 获得局部截屏图像
							Image image = ScreenImage.getScreenImage(x, y, xEnd
									- x, yEnd - y);
							// 将图片框绑定一只画笔g,将image画在bufferedImage上
							Graphics g = bufferedImage.getGraphics();
							g.drawImage(image, 0, 0, xEnd - x, yEnd - y, null);
							// 画出来的图片上会存有绿色选框,现在将绿色选框消除
							g.setColor(Color.white);
							g.drawRect(0, 0, xEnd - x, yEnd - y);
							/*
							 * 文件写入磁盘
							 */
							File selectFile = fileChooser.getSelectedFile();
							String name = selectFile.getName();
							   if (!name.endsWith("jpg")) {
							    String path = selectFile.getAbsolutePath();
							    selectFile = new File(path + ".jpg");
							    for (int i = 0; selectFile.exists(); i++) {
							    	selectFile = new File(path + "(" + i + ").jpg");
							    }
							}  
							// 输出图片
							ImageIO.write(bufferedImage, "jpg", selectFile);
							dispose();
						} else {
							label.setIcon(screenImageIcon);
						}
					} catch (Exception e2) {
						e2.printStackTrace();
						JOptionPane.showConfirmDialog(null, "出现意外错误!", "系统提示",
								JOptionPane.DEFAULT_OPTION,
								JOptionPane.ERROR_MESSAGE);
					}
				}
			}
		});

为了显示截图的预览效果,我们一般显示一个截图框:

		// 鼠标拖拽事件
		label.addMouseMotionListener(new MouseMotionListener() {
			@Override
			public void mouseDragged(MouseEvent e) {
				if (!isDrag) {
					isDrag = true;
				}
				// 拖动过程的虚线选框实现
				int endx = e.getX();
				int endy = e.getY();
				BufferedImage bufferedImage = new BufferedImage(
						screenDims.width, screenDims.height,
						BufferedImage.TYPE_INT_BGR);
				Graphics g = bufferedImage.getGraphics();
				g.drawImage(screenImageIcon.getImage(), 0, 0, screenDims.width,
						screenDims.height, null);
				g.setColor(Color.green);
				g.drawRect(x, y, endx - x, endy - y);
				label.setIcon(new ImageIcon(bufferedImage));
			}

			@Override
			public void mouseMoved(MouseEvent e) {
			}
		});

此外还有一个细节问题,通过上面大家都知道,我们是通过先全屏截图,捕获全屏图像,然后在这个全屏图像上进行矩形分割得到我们所需的局部图像,那么在全屏截取时得到的图像会出现边框,这样影响二次分割图像,我们需要对其边框的属性进行设置。代码如下:
		this.setUndecorated(true);// 将捕获的全屏图像的边框消除
		/*
		 * this就是默认你调用所定义类的实例化对象 this.getContentPane()的作用是初始化一个容器,用来在容器上添加一些控件
		 * 下面这句中,可以分开理解为: Container c = this.getContentPane();//初始化一个容器
		 * c.add(label);//在容器上添加控件
		 */
		this.getContentPane().add(label);// 将全屏图像标签添加到容器上
		this.setSize(screenDims.width, screenDims.height);
		this.setVisible(true);
		/*
		 * 设置窗口状态 参数含义 NORMAL 默认状态 ICONIFIED 最小化 MAXIMIZED_HORIZ 水平方向最大化
		 * MAXIMIZED_VERT 垂直方向最大化 MAXIMIZED_BOTH 水平方向和数值方向都最大化
		 */
		this.setExtendedState(JFrame.MAXIMIZED_HORIZ);

到这里后,整体项目就完成了。下面我把我的整个代码块附在下面,水平有限,如果有大家发现什么问题,或者觉得我哪里讲的不好,没有讲清楚,希望在下面留言板中提出,我会一一作答并吸取经验,谢谢!



1.JframeShow.java:

package SCR;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class JframeShow extends JFrame {
	private static final long serialVersionUID = -4767500078802197544L;

	public JframeShow() {
		JFrame frame = new JFrame("截屏");
		JPanel a = new JPanel();
		JLabel b = new JLabel("Ctrl+Alt截图");
		JLabel c = new JLabel("Esc退出截屏软件");
		JLabel d = new JLabel("East_MrChiu制作");
		a.add(b);
		a.add(c);
		a.add(d);
		frame.add(a);
		frame.setSize(160, 100);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
		frame.setResizable(false);// 窗体大小不可变
	}
}

2.ScreenWindow.java:

package SCR;

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Label;
import java.awt.MediaTracker;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

public class ScreenWindow extends JFrame {
	private static final long serialVersionUID = -2214091416124833614L;
	public Dimension screenDims = null;// 屏幕大小
	public ImageIcon screenImageIcon = null;// 截取的图片
	public JLabel label = null;
	private boolean isDrag = false;
	private int x = 0;
	private int y = 0;
	private int xEnd = 0;
	private int yEnd = 0;

	public ScreenWindow() throws AWTException,
			InterruptedException {
		// 捕获全屏
		screenDims = Toolkit.getDefaultToolkit().getScreenSize();// 获取整体屏幕大小内容
		screenImageIcon = new ImageIcon(ScreenImage.getScreenImage(0, 0,
				screenDims.width, screenDims.height));// 接受捕获的全屏图像
		label = new JLabel(screenImageIcon);// 将接受来的全屏图像放到标签上,以便接下来的操作
		label.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));// 设置在全屏截图图像上移动时的鼠标光标样式(这里设置成十字架样式)

		// 添加鼠标点击事件
		label.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON3) {
					dispose();
				}
			}
			public void mousePressed(MouseEvent e) {
				x = e.getX();
				y = e.getY();
			}
			public void mouseReleased(MouseEvent e) {
				if (isDrag) {
					xEnd = e.getX();
					yEnd = e.getY();
					if (x > xEnd) {
						int temp = x;
						x = xEnd;
						xEnd = temp;
					}
					if (y > yEnd) {
						int temp = y;
						y = yEnd;
						yEnd = temp;
					}

					// 保存文件
					try {
						JFileChooser fileChooser = new JFileChooser();// 构造一个文件选择器
						// 设置主目录
						// 1.固件存储位置
						// fileChooser.setCurrentDirectory(new File("D:"));
						// 2.弹出保存文件的选择框
						fileChooser.setFileFilter(new FileFilter() {
							public boolean accept(File f) {
								return f.isDirectory() || f.getName().toLowerCase().endsWith(".jpg");
							}
							public String getDescription() {
								return "*.jpg";
							}
						});
						int result = fileChooser.showSaveDialog(null);
						if (result == JFileChooser.APPROVE_OPTION) {
							/*
							 * 获取局部截屏图像
							 */
							// 创建一个等大的图片框
							BufferedImage bufferedImage = new BufferedImage(
									xEnd - x, yEnd - x,
									BufferedImage.TYPE_INT_BGR);
							// 获得局部截屏图像
							Image image = ScreenImage.getScreenImage(x, y, xEnd
									- x, yEnd - y);
							// 将图片框绑定一只画笔g,将image画在bufferedImage上
							Graphics g = bufferedImage.getGraphics();
							g.drawImage(image, 0, 0, xEnd - x, yEnd - y, null);
							// 画出来的图片上会存有绿色选框,现在将绿色选框消除
							g.setColor(Color.white);
							g.drawRect(0, 0, xEnd - x, yEnd - y);
							/*
							 * 文件写入磁盘
							 */
							File selectFile = fileChooser.getSelectedFile();
							String name = selectFile.getName();
							   if (!name.endsWith("jpg")) {
							    String path = selectFile.getAbsolutePath();
							    selectFile = new File(path + ".jpg");
							    for (int i = 0; selectFile.exists(); i++) {
							    	selectFile = new File(path + "(" + i + ").jpg");
							    }
							}  
							// 输出图片
							ImageIO.write(bufferedImage, "jpg", selectFile);
							dispose();
						} else {
							label.setIcon(screenImageIcon);
						}
					} catch (Exception e2) {
						e2.printStackTrace();
						JOptionPane.showConfirmDialog(null, "出现意外错误!", "系统提示",
								JOptionPane.DEFAULT_OPTION,
								JOptionPane.ERROR_MESSAGE);
					}
				}
			}
		});

		// 鼠标拖拽事件
		label.addMouseMotionListener(new MouseMotionListener() {
			@Override
			public void mouseDragged(MouseEvent e) {
				if (!isDrag) {
					isDrag = true;
				}
				// 拖动过程的虚线选框实现
				int endx = e.getX();
				int endy = e.getY();
				BufferedImage bufferedImage = new BufferedImage(
						screenDims.width, screenDims.height,
						BufferedImage.TYPE_INT_BGR);
				Graphics g = bufferedImage.getGraphics();
				g.drawImage(screenImageIcon.getImage(), 0, 0, screenDims.width,
						screenDims.height, null);
				g.setColor(Color.green);
				g.drawRect(x, y, endx - x, endy - y);
				label.setIcon(new ImageIcon(bufferedImage));
			}

			@Override
			public void mouseMoved(MouseEvent e) {
			}
		});

		this.setUndecorated(true);// 将捕获的全屏图像的边框消除
		/*
		 * this就是默认你调用所定义类的实例化对象 this.getContentPane()的作用是初始化一个容器,用来在容器上添加一些控件
		 * 下面这句中,可以分开理解为: Container c = this.getContentPane();//初始化一个容器
		 * c.add(label);//在容器上添加控件
		 */
		this.getContentPane().add(label);// 将全屏图像标签添加到容器上
		this.setSize(screenDims.width, screenDims.height);
		this.setVisible(true);
		/*
		 * 设置窗口状态 参数含义 NORMAL 默认状态 ICONIFIED 最小化 MAXIMIZED_HORIZ 水平方向最大化
		 * MAXIMIZED_VERT 垂直方向最大化 MAXIMIZED_BOTH 水平方向和数值方向都最大化
		 */
		this.setExtendedState(JFrame.MAXIMIZED_HORIZ);
	}

	static// 截图
	class ScreenImage {
		public static Image getScreenImage(int i, int j, int width, int height)
				throws AWTException, InterruptedException {
			Robot robot = new Robot();
			Image screen = robot.createScreenCapture(
					new Rectangle(i, j, width, height)).getScaledInstance(
					width, height, Image.SCALE_SMOOTH);
			MediaTracker tracker = new MediaTracker(new Label());
			tracker.addImage(screen, 1);
			tracker.waitForID(0);
			return screen;
		}
	}
}

3.CopyScreen.java:

package SCR;

import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class CopyScreen extends JFrame {// 继承JFrame
	private static final long serialVersionUID = -394216642885173478L;

	/*
	 * 先将整个当前屏幕内容整体截取出来
	 */
	public CopyScreen() {
		new JframeShow();
		KeyboardFocusManager manager = KeyboardFocusManager
				.getCurrentKeyboardFocusManager();// 获得监听管理器

		// 同时按下CTRL+ALT按键事件
		manager.addKeyEventPostProcessor(new KeyEventPostProcessor() {// 添加事件监听进程
			@Override
			public boolean postProcessKeyEvent(KeyEvent e) {
				// 判断是否同时按下CTRL+ALT,若是,则进行截图
				if (e.isAltDown() && e.isControlDown()) {
					try {
						setVisible(false);// 设置窗体不可见
						new ScreenWindow();// 开始下一步的截屏处理
					} catch (Exception e2) {
						JOptionPane.showConfirmDialog(null, "出现意外错误!", "系统提示",
								JOptionPane.DEFAULT_OPTION,
								JOptionPane.ERROR_MESSAGE);
					}
				}
				return false;
			}
		});

		// 按键ESC退出事件
		manager.addKeyEventPostProcessor(new KeyEventPostProcessor() {
			@Override
			public boolean postProcessKeyEvent(KeyEvent e) {
				// 判断是否按下ESC按键
				if (KeyEvent.VK_ESCAPE == e.getKeyCode()) {
					System.exit(0);// 退出程序
				}
				return false;
			}
		});
	}

	public static void main(String[] args) {
		new CopyScreen();
	}
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值