pcw550 于 2014.03.30 09:12 提问
- 我用Java 写的一个简单截图小工具 但是出现一些在重截时出现bug 跪求大神
-
/**在这里贴上我注释满满的代码 求一语道破 求建议 求批评
没有贴main 方法 随便写个main方法便可运行 */`
package com.subimaga;import java.awt.AWTException;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;import javax.imageio.ImageIO;
import javax.swing.JFrame;import com.sun.awt.AWTUtilities;
public class ScreenCapture extends JFrame implements MouseListener,
MouseMotionListener {private BufferedImage bufferedImage = null;// 用来存放图像 // 获取屏幕的大小 private int width = Toolkit.getDefaultToolkit().getScreenSize().width; private int height = Toolkit.getDefaultToolkit().getScreenSize().height; private Point point = new Point(0, height); // 截图的左上角 private Point point2 = new Point(0, 0);// 截图右下角 private Point point3 = new Point(0, 0);// 用来处理point 与point2 的关系 // 是画笔的透明度可控制 private AlphaComposite composite; boolean isStarCut = false, isEndCut = false;// isStarCut 为开始选区 // isEndCut为截图结束仅标记结束选区 public ScreenCapture() { // 初始化窗口 this.InitScr(); } private void InitScr() // 初始化 { // 截取整个桌面作为窗口的背景 try { bufferedImage = new Robot().createScreenCapture(new Rectangle(0, 0, width, height)); } catch (AWTException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 去掉窗体结构 this.setUndecorated(true); // 设置窗体大小 this.setSize(width, height); // 设置画笔的透明度 composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f); this.addMouseListener(this); this.addMouseMotionListener(this); this.setVisible(true); this.setAlwaysOnTop(true); repaint(); } public void paint(Graphics g) { // 配置截图环境 BufferedImage buff = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D g2 = buff.createGraphics(); // 画笔一 Graphics2D g3 = buff.createGraphics(); // 画笔二 用两个画笔主要是因为需要不同的透明度 g2.drawImage(bufferedImage, 0, 0, null); g2.setColor(Color.gray); g2.setComposite(composite); g2.fillRect(0, 0, width, height); // 截图的工作 if (isStarCut == true || isEndCut == true) { // 当 confirmArea(); // 处理坐标的方法 /** * 我实现的原理是 在铺了全屏截图的窗口上铺上一层灰色 透明为0.6 的实心矩形 * 根据用户在窗口拖动的坐标再另外截取一张相对应的图片铺在上面 */ g3.drawImage(bufferedImage.getSubimage(point.x, point.y, Math .abs(point2.x - point.x), Math.abs(point2.y - point.y)), point.x, point.y, null); // 画出一个绿色的空心矩形 g3.setColor(Color.green); g3.drawRect(point.x, point.y, point2.x - point.x, point2.y - point.y); } // 功能框的显示 if (isEndCut == true) { // 当选区结束 才会绘出此框 action(); // 背景框 g2.fillRect(point3.x, point3.y + 5, 200, 30); g2.setColor(Color.red); // 完成 g3.drawRect(point3.x, point3.y + 5, 60, 30); g3.setColor(Color.white); g3.drawString("完成", point3.x + 20, point3.y + 25); // 重截 g2.drawRect(point3.x + 70, point3.y + 5, 60, 30); g2.drawString("重截", point3.x + 20 + 70, point3.y + 25); // 退出 g2.drawRect(point3.x + 140, point3.y + 5, 60, 30); g2.drawString("退出", point3.x + 20 + 140, point3.y + 25); } // 双缓冲 g.drawImage(buff, 0, 0, this); } // 调节功能框位置的方法 public void action() { if (point2.x <= width - 200 && point2.y < height - 35) { point3.x = point2.x; point3.y = point2.y; } else if (point.x >= 200 && point.y >= 35) { point3.x = point.x; point3.y = point.y - 50; } else if (point.x <= 200 && point2.x >= width - 200 && point.y >= 35) { point3.x = point2.x - 205; point3.y = point.y - 50; } else if (point.y >= 35 && point2.y <= height - 35 && point2.x >= width - 200) { point3.x = point2.x; point3.y = point2.y; } else { point3.x = point2.x - 205; point3.y = point.y; } } public void confirmArea() { int temp; point.x = point3.x; // 每一次开始都是和原点坐标比较 point.y = point3.y; if (point2.x < point.x && point2.y < point.y) { temp = point.x; point.x = point2.x; point2.x = temp; temp = point.y; point.y = point2.y; point2.y = temp; } else if (point2.x < point.x) { temp = point.x; point.x = point2.x; point2.x = temp; } else if (point2.y < point.y) { temp = point.y; point.y = point2.y; point2.y = temp; } } public void actoinCut(MouseEvent e) // 操作功能框的方法 { if (isEndCut) { // 完成 if (e.getX() >= point3.x && e.getX() <= point3.x + 60 && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) { // //将截好的图保存起来 原理是利用点下完成的“按钮”时的坐标 即是最后一次决定的选区 对图片进行截图保存 try { ImageIO.write(bufferedImage.getSubimage(point.x, point.y, Math.abs(point2.x - point.x), Math.abs(point2.y - point.y)), "jpg", new File("D:/D.jpg")); } catch (IOException e1) { // // TODO Auto-generated catch block e1.printStackTrace(); } ; System.exit(0); // 保存完毕马上退出 这里的保存够工作有点简单因为只是用来测试此截图工具的bug // 具体的功能先不实现先 } // 重截 else if (e.getX() >= point3.x + 70 && e.getX() <= point3.x + 70 + 60 && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) { isEndCut = false; // 重新截图 一切进入初始状态 这个 重截一直搞不好 求大神 isStarCut = false; // 点击重截后鼠标依然保持手型样式 所以要恢复默认 setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); // 重绘 repaint(); } // 退出 else if (e.getX() >= point3.x + 140 && e.getX() <= point3.x + 140 + 60 && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) { System.exit(0); } } } public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub if (e.getButton() == MouseEvent.BUTTON3) // 双击 右键退出程序 { if (e.getClickCount() == 2) System.exit(0); } } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub // 只有当初始化状态才生效 if (isStarCut == false && isEndCut == false && e.getButton() == MouseEvent.BUTTON1) { point.x = e.getX(); point.y = e.getY(); point3.x = e.getX(); point3.y = e.getY(); isStarCut = true; } // 进入重截的条件 else if (isEndCut) { this.actoinCut(e); } } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub // 截图开始生效 if (isStarCut && isEndCut == false && e.getButton() == MouseEvent.BUTTON1) { isEndCut = true; // 鼠标一放开马上标记截图结束 isStarCut = false; // 重新标记未开始选区状态 repaint();// 重绘 } } @Override public void mouseDragged(MouseEvent e) { // TODO Auto-generated method stub // 拖动是改变矩形的坐标点 if (isStarCut || isEndCut) { point2.x = e.getX(); point2.y = e.getY(); repaint(); } } public void mouseMoved(MouseEvent e) { // TODO Auto-generated method stub // 在功能框上显示手型状态 if (isEndCut) { // 完成 if (e.getX() >= point3.x && e.getX() <= point3.x + 60 && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) { setCursor(new Cursor(Cursor.HAND_CURSOR)); } // 重截 else if (e.getX() >= point3.x + 70 && e.getX() <= point3.x + 70 + 60 && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) { setCursor(new Cursor(Cursor.HAND_CURSOR)); } // 退出 else if (e.getX() >= point3.x + 140 && e.getX() <= point3.x + 140 + 60 && e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) { setCursor(new Cursor(Cursor.HAND_CURSOR)); } else { setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } }
}
-
- wodeqiantu2010 2014.04.12 18:24
- 已采纳
int needWh = Math.abs(point2.x - point.x);
int needhg = Math.abs(point2.y - point.y);
if ((isStarCut || isEndCut) && needWh != 0 && needhg != 0) {
confirmArea(); // 处理坐标的方法
//将选择的矩形图片截出来
BufferedImage needScr = bufferedImage.getSubimage(point.x, point.y, needWh, needhg);
//截出来以后重新画在jframe上,覆盖原先背景图片,以不同的透明度
g3.drawImage(needScr,point.x, point.y, null);
g3.setColor(Color.RED);
g3.drawRect(point.x, point.y, point2.x - point.x, point2.y - point.y);
}
确定所选区域为正方形才继续截图,这样就不会报错。
其实最根本的原因在这个地方,就是当你点击完成、重截、退出的时候同样会触发mouseReleased事件,只要加一个标志就可以了:
boolean isRecapt = false; //标记是否是重新截图
boolean isComplt = false; //标记是否完成截图
boolean isExit = false; //标记是否是退出
public void actoinCut(MouseEvent e) // 操作功能框的方法
{
if (isEndCut) {
// 完成
if (e.getX() >= point3.x && e.getX() <= point3.x + 60
&& e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {
isComplt = true;
//将截好的图保存起来 原理是利用点下完成的“按钮”时的坐标 即是最后一次决定的选区 对图片进行截图保存
try {
ImageIO.write(bufferedImage.getSubimage(point.x, point.y,
Math.abs(point2.x - point.x), Math.abs(point2.y
- point.y)), "jpg", new File("JAVA截图_" + System.currentTimeMillis() + ".jpg"));
} catch (IOException e1) {
e1.printStackTrace();
};
System.exit(0);
}
// 重截
else if (e.getX() >= point3.x + 70
&& e.getX() <= point3.x + 70 + 60
&& e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {
isEndCut = false; // 重新截图 一切进入初始状态 这个 重截一直搞不好 求大神
isStarCut = false;
isRecapt = true; //重新截图置为true
// 点击重截后鼠标依然保持手型样式 所以要恢复默认
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
// 重绘
repaint();
}
// 退出
else if (e.getX() >= point3.x + 140
&& e.getX() <= point3.x + 140 + 60
&& e.getY() >= point3.y + 5 && e.getY() <= point3.y + 35) {
isExit = true;
System.exit(0);
}
}
}
public void mouseReleased(MouseEvent e) {
//当点击完成、重截、退出以后,现有程序会将释放鼠标(Release)的动作视为截图动作的开始,这显然是错误的,因此要过滤掉。
if (isRecapt || isComplt || isExit){
System.out.println("我return了 mouseReleased");
isRecapt = false;
repaint();// 重绘
return ;
}
// 截图开始生效
if (isStarCut && isEndCut == false
&& e.getButton() == MouseEvent.BUTTON1) {
isEndCut = true; // 鼠标一放开马上标记截图结束
isStarCut = false; // 重新标记未开始选区状态
repaint();// 重绘
}
}
- 其他相关推荐