14 screenShotLikeQQ
来源:互联网 发布:淘宝刷单被骗案例 编辑:程序博客网 时间:2024/05/17 02:11
前言
根据上一篇播客的博主的播客, 我发现了 博主有很多swing相关的播客, 就没事 看了一看, 闲来蛋疼 就参考着做了一些有意思的案例, so ..
此代码参考了 一些该博主的一些swing相关技巧
问题描述
做一个截图工具, 要求如下, 在程序启动之后 截取当前屏幕的状态, 然后 用户选择需要截取的部分, 用户在选择的图片之上双击之后, 将其保存到剪切板
思路
思路 : 截图 使用robot截图, 绘制用户选中区域使用swing相关控件, 拖拽的时候 更新该控件的坐标 以及新位置的截取的图片
难点 : 1 对于swing的一些效果的掌握, 比如 全屏, 方格效果等等
2 对于用户是否更新截取部分的逻辑的处理
3 对于用户拖拽截取部分 越界的处理
其余部分, 请详见代码
参考代码
/** * file name : Test14QQSnapShot.java * created at : 9:28:54 PM Nov 24, 2015 * created by 970655147 */package com.hx.test08;// 仿qq截图public class Test14QQSnapShot extends JFrame { // 参考 : http://blog.csdn.net/ycb1689/article/details/8017396 // robot [截图] private static Robot robot; static { try { robot = new Robot(); } catch (AWTException e) { e.printStackTrace(); } } // 背景色, 整个屏幕的大小 // 存放当前屏幕图片的label, 存放截取的部分图片的label, 存放截取部分图片的ImageIcon private Color bgColor = new Color(200,150,150); private Dimension screenSize; private JLabel label; private JLabel subImg; private ImageIcon subImgIcon; // 初始化 // 1. 配置当前JFrame // 2. 添加元素 // 3. 为当前JFrame配置KeyListener, 配置退出当前程序的按键 // 4. 配置当前JFrame的MouseListener, 用于控制鼠标的相应操作 public Test14QQSnapShot() { setLayout(null); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(getScreenSize() ); setExtendedState(MAXIMIZED_BOTH); setResizable(false); // 这里不将其设置为top窗口的目的是为了多次截图// setAlwaysOnTop(true); setUndecorated(true); setTitle("snapshot"); // subImg 需要放到全屏幕截图的label的前面 // 获得整个屏幕的截图 final BufferedImage allScreenImg = robot.createScreenCapture(new Rectangle(0, 0, getScreenSize().width, getScreenSize().height)); subImg = new JLabel(); subImg.setBorder(BorderFactory.createLineBorder(Color.GREEN, 2) ); subImgIcon = new ImageIcon(); subImg.setIcon(subImgIcon); MouseAdapter dragAdpater = new SubImageAdapter(subImg, subImgIcon, allScreenImg); subImg.addMouseListener(dragAdpater); subImg.addMouseMotionListener(dragAdpater); add(subImg); label = new JLabel(){ protected void paintComponent(Graphics g) { super .paintComponent(g); g.drawImage(allScreenImg, 0, 0, this); Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(bgColor); // fill的时候, 使用的色度 AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 40 /100.0F ); g2d.setComposite(composite); g2d.fill(new RoundRectangle2D.Float(0, 0, this .getWidth(), this.getHeight(), 0, 0 ) ); } }; label.setBounds(0, 0, getWidth(), this.getHeight()); add(label); // 保证截图的时候, 不会截到"Test14QQSnapShot"的窗口, 而是当前状态屏幕的窗口 setVisible(true); // for 'esc' exit addKeyListener(new KeyListener() { public void keyTyped(KeyEvent e) { } public void keyReleased(KeyEvent e) { } public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_ESCAPE) { Test14QQSnapShot.this.dispose(); System.exit(0); } } }); MouseAdapter adapter = new ScreenShotDragMouseAdapter(this, allScreenImg); addMouseListener(adapter); addMouseMotionListener(adapter); } // main public static void main(String []args) { new Test14QQSnapShot(); } // 获取整个屏幕的大小 private Dimension getScreenSize() { if(screenSize == null) { screenSize = Toolkit.getDefaultToolkit().getScreenSize(); } return screenSize; } // 部分截图的MouseAdpater static class ScreenShotDragMouseAdapter extends MouseAdapter { // 整个屏幕的截图, 截取的部分截图, 是否截取过图片, 是否开始截取部分图片 // 截取开始的坐标 private Test14QQSnapShot parentFrame; private BufferedImage allScreenImg; private boolean isCuted; private boolean isStart; private Point start = new Point(); private Dimension dimen = new Dimension(); // 初始化 public ScreenShotDragMouseAdapter(Test14QQSnapShot parentFrame, BufferedImage allScreenImg) { this.parentFrame = parentFrame; this.allScreenImg = allScreenImg; } // 1. 如果截过图, 判断当前点击的点是否在原截图的方框之中 // 如果在, 则不能重新截图[需要拖动该图 [SubImgMouseAdapter] ] // 否则, 更新标志变量重新截图 // 2. 记录start @Override public void mousePressed(MouseEvent e) { if(isCuted ) { java.awt.Point pointNow = new java.awt.Point(e.getX(), e.getY()); if(! isPointInRect(pointNow, parentFrame.subImg.getLocation(), parentFrame.subImg.getSize()) ) { isCuted = false; } } if(! isCuted) { start.x = e.getX(); start.y = e.getY(); } } // 记录dimen @Override public void mouseReleased(MouseEvent e) { if(! isCuted) { isCuted = true; dimen.width = e.getX() - start.x; dimen.height = e.getY() - start.y; } } // 如果没有结果图 [isCuted在MouseRelease中更新] // 获取当前截图的start, dimen[如果 dimen.width 或者dimen.height 小于0, 则更新start, dimen[更新为符合条件[dimen.width & dimen.height 大于0]的等价表示] ] // 然后 判断截图的部分是否超出边界, 以及dimen.width 或者dimen.height 可能为0, 如果校验通过, 进行截图, 更新parentFrame.subImgIcon, 以及parentFrame.subImg.location @Override public void mouseDragged(MouseEvent e) { if(! isCuted) { Dimension dimenNow = new Dimension(); dimenNow.width = e.getX() - start.x; dimenNow.height = e.getY() - start.y; int startX = start.x, startY = start.y; if(dimenNow.width < 0) { dimenNow.width = (- dimenNow.width); startX -= dimenNow.width; } if(dimenNow.height < 0) { dimenNow.height = (- dimenNow.height); startY -= dimenNow.height; } if((startX + dimenNow.width < parentFrame.getScreenSize().getWidth()) && (startY + dimenNow.height < parentFrame.getScreenSize().getHeight()) && (dimenNow.width > 0) && (dimenNow.height > 0) ) { parentFrame.subImgIcon.setImage(allScreenImg.getSubimage(startX, startY, dimenNow.width, dimenNow.height) ); parentFrame.subImg.setBounds(startX, startY, dimenNow.width, dimenNow.height); } } } // 判断给定的点是否在给定的矩形内 private boolean isPointInRect(java.awt.Point pos, java.awt.Point start, Dimension dimen) { return (pos.x > start.x) && (pos.y > start.y) && (pos.x < start.x + dimen.width) && (pos.y < start.y + dimen.height); } } // 拖拽的MouseListener public class SubImageAdapter extends MouseAdapter { // 操作的frame, 整个屏幕的截图 private Component subImg; private BufferedImage allScreenImg; private int lastX = -1; private int lastY = -1; // 初始化 public SubImageAdapter(Component subImg, ImageIcon subImgIcon, BufferedImage allScreenImg) { super(); this.subImg = subImg; this.allScreenImg = allScreenImg; } // 记录拖拽之前点击的坐标 @Override public void mousePressed(MouseEvent e) { lastX = e.getX(); lastY = e.getY(); } // 判断拖拽之后元素是否超出屏幕 // 如果没有, 则进行更新截图subImgIcon.img, 更新subImg.location @Override public void mouseDragged(MouseEvent e) { java.awt.Point start = subImg.getLocation(); Dimension dimen = subImg.getSize(); start.x += e.getX() - lastX; start.y += e.getY() - lastY; start.x = start.x > 0 ? start.x : 0; start.y = start.y > 0 ? start.y : 0; start.x = (start.x + dimen.width < getScreenSize().getWidth() ) ? start.x : ((int) getScreenSize().getWidth() - dimen.width); start.y = (start.y + dimen.height < getScreenSize().getHeight() ) ? start.y : ((int) getScreenSize().getHeight() - dimen.height); subImg.setLocation(start ); subImgIcon.setImage(allScreenImg.getSubimage(start.x, start.y, dimen.width, dimen.height) ); } // 进行保存图片到剪切板的操作, 并更新subImg, 以便于下一次截图 @Override public void mouseClicked(MouseEvent e) { if(e.getClickCount() > 1) { Tools.copyImgToClipBoard((RenderedImage) subImgIcon.getImage() ); subImg.setSize(0, 0); } } }}
效果截图
总结
小工具, 扯扯淡, 向原作者致敬 !
参考 :
http://blog.csdn.net/ycb1689/article/details/8017396
注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!
0 0
- 14 screenShotLikeQQ
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 14
- 用栈判断回文
- Fuel Openstack 7.0在Virtualbox中部署
- %运算符 1
- (4)shell替换
- MySQL教程-原理篇-B+Tree索引
- 14 screenShotLikeQQ
- 【大话设计模式】六大原则
- 搭建一个struts2+spring+hibernate框架
- 导入AndroidStudio的项目卡死,如何快速导入AndroidStudio的项目
- 【三层学习】——初识
- ubuntu下apache2 安装 配置 卸载 CGI设置 SSL设置
- BZOJ 1013: [JSOI2008]球形空间产生器sphere
- HDU-1026 Ignatius and the Princess I (BFS)
- bzoj2333 棘手的操作 可并堆or dfs序列+线段树