`

Swing 实现截图小软件 (三)

阅读更多

 

前面两节完成了,截图软件的基本功能:全屏,区域截图 功能

 

本节实现:涂鸦 画线 画圈 保存

 

第一步:实现涂鸦功能。

  涂鸦也就是说:使用鼠标随意的拖动,去绘制随意的线条。那么就只需要在主程序的展示截图的JLabel中添加鼠标拖动监听。在鼠标每个移动点是绘制“一个点”,这样就可以按照鼠标的移动轨迹,来绘制任意的线条了。

 

 按照上面的思路给出代码:SnapShoot.java

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;

import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 * 屏幕截图小程序
 * @author pengranxiang
 *
 */
public class SnapShoot extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JButton snapButton;
	private JLabel imageLabel;
	
	private int x, y;	//记录鼠标坐标
	
	public SnapShoot() {
		initUI();
		initLayout();
		createAction();
		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setSize(600, 400);
		this.setTitle("截图小工具");
		this.setLocationRelativeTo(null);	//居中
		this.setVisible(true);
	}
	
	private void initUI() {
		snapButton = new JButton("开始截图(点右键退出)");
		imageLabel = new JLabel();
	}
	
	private void initLayout() {
		JPanel pane = new JPanel();
		pane.add(imageLabel);
		JScrollPane imgScrollPane = new JScrollPane(pane);
		
		Container container = this.getContentPane();
		GroupLayout layout = new GroupLayout(container);
		container.setLayout(layout);
		
		layout.setAutoCreateContainerGaps(true);
		layout.setAutoCreateGaps(true);
		
		GroupLayout.ParallelGroup hGroup = layout.createParallelGroup();
		hGroup
			.addComponent(snapButton)
			.addComponent(imgScrollPane);
		layout.setHorizontalGroup(hGroup);
		
		GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
		vGroup
			.addComponent(snapButton)
			.addComponent(imgScrollPane);
		layout.setVerticalGroup(vGroup);
	}
	
	private void createAction() {
		snapButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					//开启模拟屏幕,将显示截图的目标组件传入
					new ScreenWindow(imageLabel);
				} catch (AWTException e1) {
					e1.printStackTrace();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		});
		
		imageLabel.addMouseMotionListener(new MouseMotionListener() {
			public void mouseDragged(MouseEvent e) {
				x = e.getX();
				y = e.getY();
				
				//鼠标移动时,在imageLabel展示的图像中,绘制点
				//1. 取得imageLabel中的图像
				Image img = ((ImageIcon)imageLabel.getIcon()).getImage();
				
				//2. 创建一个缓冲图形对象 bi
				BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
				Graphics2D g2d = (Graphics2D) bi.getGraphics();
				
				//3. 将截图的原始图像画到 bi
				g2d.drawImage(img, 0, 0, null);
				
				//4. 在鼠标所在的点,画一个点
				g2d.setColor(Color.RED);	//设置画笔颜色为红色
				g2d.drawLine(x, y, x, y);	//Java中没有提供点的绘制,使用起点和终点为同一个点的画线代替
				
				g2d.dispose();
				
				//5. 为了保留每一个点,不能直接使用imageLabel.getGraphics()来画,
				//需要使用imageLabel.setIcon()来直接将画了点的图像,设置到imageLabel中,
				//这样,在第一步中,取得img时,就为已经划过上一个点的图像了。
				imageLabel.setIcon(new ImageIcon(bi));
			}

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

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

 

运行该代码,发现在涂鸦时,跟踪鼠标画的点,太过分散,不连续。鼠标移动越快,点就越不连续。如图:


可见,在监听鼠标移动时,画点的速度,跟不上鼠标移动的速度。又图想到,如果把上面的散点全部连接起来,则可以构成一条平滑的线了。

 

于是:改变思路,由画点,改为画线。将鼠标移动监听到的每一个点,都首尾连接的画线。

节约篇幅:展示修改的部分代码,在createActon()中

imageLabel.addMouseListener(new MouseAdapter() {
	public void mousePressed(MouseEvent e) {
		//鼠标按下的点,作为画线的最初的起点
		x = e.getX();
		y = e.getY();
	}
});

imageLabel.addMouseMotionListener(new MouseMotionListener() {
	public void mouseDragged(MouseEvent e) {
		xEnd = e.getX();
		yEnd = e.getY();
		
		//鼠标移动时,在imageLabel展示的图像中,绘制点
		//1. 取得imageLabel中的图像
		Image img = ((ImageIcon)imageLabel.getIcon()).getImage();
		
		//2. 创建一个缓冲图形对象 bi
		BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
		Graphics2D g2d = (Graphics2D) bi.getGraphics();
		
		//3. 将截图的原始图像画到 bi
		g2d.drawImage(img, 0, 0, null);
		
		//4. 在鼠标所在的点,画一个点
		g2d.setColor(Color.RED);	//设置画笔颜色为红色
		g2d.drawLine(x, y, xEnd, yEnd);	//将画点,改为画线
		
		g2d.dispose();
		
		//5. 为了保留每一个点,不能直接使用imageLabel.getGraphics()来画,
		//需要使用imageLabel.setIcon()来直接将画了点的图像,设置到imageLabel中,
		//这样,在第一步中,取得img时,就为已经划过上一个点的图像了。
		imageLabel.setIcon(new ImageIcon(bi));
		
		//下次画线起点是设置为这次画线的终点
		x = xEnd;
		y = yEnd;
	}

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

 

改变思路后,涂鸦的线条效果,就好多了。如图:

 

 

 

第二步:实现画线功能。

   画线的话,与涂鸦有点不同。 涂鸦是根据鼠标移动实时画线。 而画线功能要求是:从鼠标按下, 到鼠标弹起的两点之间画一条线段。鼠标移动时,只是展示最后效果,并不直接画上去。 鼠标弹起后,才真的画上去。

 

  同时因为,有了连个功能,我们给个功能开关,是要涂鸦,还是要画线。

 代码片段:createAction() 中

 

imageLabel.addMouseListener(new MouseAdapter() {
	public void mousePressed(MouseEvent e) {
		//鼠标按下的点,作为画线的最初的起点
		x = e.getX();
		y = e.getY();
	}
	
	public void mouseReleased(MouseEvent e) {
		if(isLine) {
			//该方法只用作画线时处理
			//鼠标弹起时需要将最后定为的图像 bi,调用imageLabel.setIcon()方法,设置进去。
			//这样就可以将线段真的画进去了。为了使用变量 bi 将其转为 该类的private变量
			imageLabel.setIcon(new ImageIcon(bi));
		}
	}
});

imageLabel.addMouseMotionListener(new MouseMotionListener() {
	public void mouseDragged(MouseEvent e) {
		
		if(isDoodle) {	//涂鸦开关
			xEnd = e.getX();
			yEnd = e.getY();
			
			//鼠标移动时,在imageLabel展示的图像中,绘制点
			//1. 取得imageLabel中的图像
			Image img = ((ImageIcon)imageLabel.getIcon()).getImage();
			
			//2. 创建一个缓冲图形对象 bi
			bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
			Graphics2D g2d = (Graphics2D) bi.getGraphics();
			
			//3. 将截图的原始图像画到 bi
			g2d.drawImage(img, 0, 0, null);
			
			//4. 在鼠标所在的点,画一个点
			g2d.setColor(Color.RED);	//设置画笔颜色为红色
			g2d.drawLine(x, y, xEnd, yEnd);	//Java中没有提供点的绘制,使用起点和终点为同一个点的画线代替
			
			g2d.dispose();
			
			//5. 为了保留每一个点,不能直接使用imageLabel.getGraphics()来画,
			//需要使用imageLabel.setIcon()来直接将画了点的图像,设置到imageLabel中,
			//这样,在第一步中,取得img时,就为已经划过上一个点的图像了。
			imageLabel.setIcon(new ImageIcon(bi));
			
			//下次画线起点是设置为这次画线的终点
			x = xEnd;
			y = yEnd;
		}
		
		if(isLine) {	//画线开关
			xEnd = e.getX();
			yEnd = e.getY();
			
			//鼠标移动时,在imageLabel展示的图像中,绘制点
			//1. 取得imageLabel中的图像
			Image img = ((ImageIcon)imageLabel.getIcon()).getImage();
			
			//2. 创建一个缓冲图形对象 bi
			bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB);
			Graphics2D g2d = (Graphics2D) bi.getGraphics();
			
			//3. 将截图的原始图像画到 bi
			g2d.drawImage(img, 0, 0, null);
			
			//4. 在鼠标所在的点,画一个点
			g2d.setColor(Color.RED);	//设置画笔颜色为红色
			g2d.drawLine(x, y, xEnd, yEnd);	//Java中没有提供点的绘制,使用起点和终点为同一个点的画线代替
			
			g2d.dispose();
			
			//5. 不需要保留在鼠标拖动过程中所画的线段,所以直接使用imageLabel.getGraphics()绘制
			//这样imageLabel.getIcon()并没有被改变,所以每次都只到原始截图和多了一条线,即为最后效果的演示
			Graphics g = imageLabel.getGraphics();
			g.drawImage(bi, 0, 0, null);	//将处理后的图片,画到imageLabel
			g.dispose();
		}
	}
 

运行情况如图:


完整代码,见附件:SnapShoot1.jar  源码在 jar 包中。

 

第三步:实现画圈功能。

  画圈的功能实现与画线就很想了, 只是修改一下,drawLine -- >  drawOval

 

 代码片段:

 
if(isLine) {
	g2d.drawLine(x, y, xEnd, yEnd);	//Java中没有提供点的绘制,使用起点和终点为同一个点的画线代替
}
if(isCircle) {
	//因为如果鼠标向上,或向左移动时,xEnd > x, yEnd > y ,所以画圆的起点要取两者中的较小的,
	//而宽度和高度是不能  < 0 的,所以取绝对值
	g2d.drawOval(Math.min(x, xEnd), Math.min(y, yEnd), Math.abs(xEnd - x), Math.abs(yEnd - y));
}

 

运行如图:


完成代码见附件:SnapShoot2.jar  源码在 jar 包中。

 

第四步: 为了然该小软件有点用处,光截图,涂鸦之类的,只能看不能用。所以现在就加入 保存 功能吧。

 

代码片段:

chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & PNG Images", "jpg", "png");
chooser.setFileFilter(filter);
		
saveButton = new JButton("保存");

saveButton.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
		if(imageLabel.getIcon() == null) {
			JOptionPane.showMessageDialog(SnapShoot.this, "没有图片信息,请先截图", "提示", JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		
		File file = null;
		int returnVal = chooser.showOpenDialog(SnapShoot.this);
	    if(returnVal == JFileChooser.APPROVE_OPTION) {
	       file = chooser.getSelectedFile();
	    }

	    //取得imageLabel中的图像
	    Image img = ((ImageIcon)imageLabel.getIcon()).getImage();
	    
		try {
			if(file != null)  {
				ImageIO.write((BufferedImage)img, "png", file);
				JOptionPane.showMessageDialog(SnapShoot.this, "保存成功", "提示", JOptionPane.INFORMATION_MESSAGE);
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
});

 运行如图:


完成代码见附件:SnapShoot3.jar 源码在 jar 包中

 

最后,界面是丑了点啦。。。

 

想要稍微让界面好看点,可以修改 LookAndFeel 为本地皮肤,修改  main()方法

public static void main(String[] args) {
	try {
		UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		JFrame.setDefaultLookAndFeelDecorated(true);
	} catch (Exception e) {
		System.out.println("Error setting native LAF: " + e);
	}
	new SnapShoot();
}

 

如图:

 

完成代码见附件:SnapShoot.jar  源码在 jar 包中

 

到此,该小软件还剩下,水印功能。 明天继续。。。O(∩_∩)O~

  • 大小: 16.2 KB
  • 大小: 18.2 KB
  • 大小: 15.5 KB
  • 大小: 16.9 KB
  • 大小: 24.3 KB
  • 大小: 43.1 KB
分享到:
评论
3 楼 pywepe 2011-03-08  
很久没上javaeye swing,发现有这么多更新,可惜现在工作了,忙,没空研究
2 楼 java_xiaoyi 2011-02-25  
恩,应该挺有趣的。。。。
1 楼 zhou363667565 2011-02-25  
呵呵,下载了,有时间看一下。

相关推荐

    Swing 实现截图小软件 (五)

    NULL 博文链接:https://pengranxiang.iteye.com/blog/935433

    swing实现的仿qq截图小工具

    本项目是使用Swing实现的一个仿QQ截图小工具,它旨在提供类似QQ截图的功能,让用户在桌面环境中能够方便地进行屏幕截图并进行编辑。 首先,Swing组件库提供了丰富的组件,如JFrame、JButton、JPanel等,这些组件...

    java swing 截屏软件实现

    以下是对这个"java swing 截屏软件实现"的详细知识点解析: 1. **Swing组件**: Swing提供了一套丰富的组件库,如JFrame、JButton、JLabel等,用于构建用户界面。在这个截屏软件中,可能会用到JFrame作为主窗口,...

    java swing 实现的带启动界面的简易截图软件

    java swing 实现的带启动界面的简易截图软件,启动界面有进度条,可保存可粘贴到qq微信,简单实用

    java swing实现pdf阅读器

    总的来说,用Java Swing实现一个PDF阅读器是一个涉及多方面技能的任务,包括对PDF格式的理解、Java GUI编程、IO操作以及第三方库的熟练使用。通过不断学习和实践,可以构建出功能强大且用户友好的PDF阅读器。

    java swing实现学生住宿管理系统(源码)

    java swing实现学生住宿管理系统(源码) java swing实现学生住宿管理系统(源码) java swing实现学生住宿管理系统(源码) java swing实现学生住宿管理系统(源码) java swing实现学生住宿管理系统(源码) java ...

    Swing小管理项目源码

    【Swing小管理项目源码】是一个基于Java Swing开发的桌面应用程序示例,它涵盖了多个核心功能,包括用户界面的设计、数据操作以及交互逻辑。Swing是Java的标准库,用于构建图形用户界面(GUI),提供了丰富的组件库...

    基于Java Swing实现的日历记事本系统【源码+报告文档】

    本项目是一套基于Java Swing实现的日历记事本系统,主要针对计算机相关专业的正在学习java的学生与需要项目实战练习的Java学习者。 包含:项目源码、报告文档等。 项目都经过严格调试,确保可以运行! 该系统功能...

    使用Java Swing实现了抖音上的表白程序

    最后,作者想说的是,1.9块钱的资源,你买不了吃亏,买不了上当,只需省一片绿箭口香糖的钱,你就能拥有一个用于整蛊的Java Swing实现,你在玩的过程中,还可以初步了解一些Java Swing的知识,如此说来,少年,抓紧时间下载吧。

    javaswing实现贪吃蛇源码

    java贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇javaswing实现贪吃蛇...

    Java基于Swing实现的简单聊天室,支持多人在线闲谈.zip

    这个“Java基于Swing实现的简单聊天室,支持多人在线闲谈.zip”文件是一个示例项目,展示了如何利用Swing构建一个基本的多用户聊天应用。下面将详细阐述其涉及的关键知识点。 1. **Swing组件**:Swing提供了丰富的...

    JAVA Swing 实现商品列表,数量加减 ,删除整行 Demo

    在这个特定的Demo中,我们关注的是如何使用Swing来实现一个商品列表,其中包含商品的数量加减功能以及整行删除的功能。这个功能通常在电商应用或者库存管理软件中会用到。 首先,我们需要了解`JTable`,这是Swing中...

    java swing写的聊天软件

    本项目"java swing写的聊天软件"利用了Swing组件来设计和实现了一个能够支持多达1000个用户同时在线的聊天应用。以下是关于这个聊天软件的关键知识点和实现细节: 1. **Swing组件库**:Swing 提供了丰富的组件,如...

    java小游戏 (源码)swing五子棋源代码

    java小游戏 (源码)swing五子棋源代码java小游戏 (源码)swing五子棋源代码java小游戏 (源码)swing五子棋源代码java小游戏 (源码)swing五子棋源代码java小游戏 (源码)swing五子棋源代码java小游戏 (源码)swing五子棋源...

    基于Java swing组件实现简易计算器

    8. Java swing组件的使用:Java swing组件可以用于创建各种图形化用户界面,例如计算器、游戏、聊天软件等。 9. 计算器的实现:计算器是Java swing组件中的一种常见应用,通过使用JFrame、JButton、JPanel、...

    Swing写的一个简易记事小软件

    标题中的“Swing写的一个简易记事小软件”指的是使用Java Swing库开发的一款简单应用程序,主要用于记录日常事项。Swing是Java提供的一种图形用户界面(GUI)工具包,它允许开发者创建桌面应用,包括窗口、按钮、...

    Java swing实现的一款餐厅点餐系统

    本项目是一套Java swing实现的一款餐厅点餐系统,主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目可以直接作为bishe使用。 项目都经过严格调试,...

    java 截屏 swing

    "java 截屏 swing"这个主题涉及到的是如何利用Swing来实现屏幕截图功能。在这个项目中,开发人员创建了一个应用程序,允许用户选择屏幕上的任意矩形区域进行截图,未被选中的部分会显示为阴影效果,同时支持拖动和...

    Java swing实现学生信息管理系统源码.zip

    《Java Swing实现学生信息管理系统》是一个基于Java Swing GUI工具集开发的应用程序,旨在提供一个高效、直观的方式来管理学校或教育机构中学生的信息。该系统的核心功能包括学生信息的录入、查询、更新和删除。通过...

    java swing做的通讯录软件连接sql

    【Java Swing制作的通讯录软件与SQL数据库连接】 在编程领域,Java Swing 是一个用于创建图形用户界面(GUI)的工具包,它提供了丰富的组件和功能,使得开发者能够构建出功能完善的桌面应用。本项目是一个基于Java ...

Global site tag (gtag.js) - Google Analytics