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

来源:互联网 发布:java面向对象试题 编辑:程序博客网 时间:2024/06/06 06:37

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


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

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


      涉及到的知识点:

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

      实现大概原理:

                        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() {// 添加事件监听进程@Overridepublic 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() {@Overridepublic 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));}@Overridepublic 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() {@Overridepublic 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));}@Overridepublic 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 {// 继承JFrameprivate static final long serialVersionUID = -394216642885173478L;/* * 先将整个当前屏幕内容整体截取出来 */public CopyScreen() {new JframeShow();KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();// 获得监听管理器// 同时按下CTRL+ALT按键事件manager.addKeyEventPostProcessor(new KeyEventPostProcessor() {// 添加事件监听进程@Overridepublic 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() {@Overridepublic boolean postProcessKeyEvent(KeyEvent e) {// 判断是否按下ESC按键if (KeyEvent.VK_ESCAPE == e.getKeyCode()) {System.exit(0);// 退出程序}return false;}});}public static void main(String[] args) {new CopyScreen();}}







0 0