java应用——高仿XP画板(三:加上重绘功能)
2017-12-01 19:11
309 查看
XP画板到今天可以说已经基本实现完毕,出了菜单栏部分的功能。不过我写的代码在实现部分依然有一点缺陷,我会继续更新这篇博客,来完善功能。
首先,从一个大体上来叙述整个代码的实现。
(一)一个Test_main函数为主函数,只有一个功能就是作为整个代码的入口来启动函数,而主函数打开的门是XPDraw类的initJFrame方法,这个方法是用来构建整个窗体的样式。所有的监听和重绘等功能在这个窗体展开。
(二)先从监听来说,我设了两个监听。
【】一个WestGraphListener类继承了MouseListener和MouseMotionListener来实现鼠标监听和鼠标拖动监听,关于鼠标系列的监听器,只要记住关键点就是,它用来监听容器类,时刻记住这点,你要用它监听什么,就把什么绑上这个监听器,因为我要实现的是在画布上作画,即我规定鼠标监听器的作用范围是画布,所以
其中传过去的参数这样来理解,我在监听器上我要用到的信息是什么。
1)我需要用到的重要信息自然是画笔,可以根据鼠标的动作在屏幕上留下痕迹的东西,因为鼠标的不断移动变化,自然不能将什么东西绑在鼠标上,所以GUI提供了一种画笔,你要在什么容器上面作画,你就从什么容器上获取画笔
2)比如我想实现不同画笔的实现,那么我就要得到我所点击的西边区域那些画笔的信息,本来要得到那些画笔的信息,也应该在那些按钮上绑定监听器,但是因为按钮组有强大的可以获取到相应信息的功能
所以就不需要绑定监听器了,直接把按钮组当做参数传给监听器就可以了,但是其他的实现还是需要单选按钮绑上监听器,这里先不说。
【】另一个SouthColorListener类继承了ActionListener类来实现事件监听,关于事件监听记住关键点,这是监听按钮组件的,前面说过因为单选按钮的按钮组有强大的获取单选按钮的事件信息,不过也可以给单选按钮绑上事件监听器来实现其他的动作,比如下面子面板(各个画笔的粗细的选项面板)的切换。
嗯,南边区域的颜料盘也是一个个按钮组成的,所以要实现颜色的切换,就可以给这些按钮绑上事件监听器
这个事件监听器的实现代码比较少
(三)各种画笔功能的实现
数一下,可以发现我们的西边区域的画笔有16个格子,即16种画笔要实现,可以用if else来进行画笔的选择,不急,可以先把画笔划分到几个不同的鼠标监听里
1)先是MouseListener类的mouseReleased方法,在这方法里,什么图形是在鼠标释放的瞬间形成的?直线,矩形,椭圆,圆矩形还有取色的功能,至于具体的实现,可以查阅API中graphics类下的各种方法实现,在下一章博客我也会把完整的代码贴出来。
不过可以说一下其中取色器的实现,取色器里用到了robot机器人类,做到自动获取屏幕中信息的功能,用机器人类可以实现远程监听呢。
2)然后是MouseMotionListener类的mouseDragged(拖动)方法,什么图形是鼠标一边拖动一边形成的呢?橡皮擦,铅笔,刷子,喷枪。
这几个图形用到的方法其实都是画直线的方法,只是比画直线多了一些技巧,比如喷枪的实现:
(四)不算最后的实现:重绘
重绘的原理即是重写JFrame类里的paint方法,我们计算机的存储有三种,硬盘,内存,闪存(CPU)。内存存电脑正在运行的数据,闪存存屏幕上出现的数据。你创建的窗体对象,缩小了再放大,关于它的属性大小标题什么的原封不动的重现在屏幕上,但你在这个窗体对象上画的画,没有重现,为什么?因为你创建的窗体是对象,内存存了它的数据,但你画的东西都只是临时的,内存并没有存下,所以CPU没法从内存里得到你画下的东西的数据,然后再重现在屏幕上。
你重写一个继承JFrame类里的paint方法:
为什么要把paint方法放在画布里?因为你重绘要用到的画笔应该是来自画布的,保持了作画和重绘的一致性。
自然,要存。用什么存?
用数组队列来存,存下一个个被封装了的图形对象MyShape,然后调用MyShape里的draw方法,将一个个对象重新画出来。在MyShape类里面,封装好一个个图形要用到的坐标数据和颜色以及画笔的粗细。
再用一个个子类来继承这个抽象类,来实现各种图形的绘制和重绘,做到封装的效果,比如直线类:
整体的画板实现思路就是这样了,画板->监听->多图形实现->重绘。完整的代码在下一章贴出来,总共有九个类,类多不要紧,只要业务实现逻辑对就行。
首先,从一个大体上来叙述整个代码的实现。
(一)一个Test_main函数为主函数,只有一个功能就是作为整个代码的入口来启动函数,而主函数打开的门是XPDraw类的initJFrame方法,这个方法是用来构建整个窗体的样式。所有的监听和重绘等功能在这个窗体展开。
(二)先从监听来说,我设了两个监听。
【】一个WestGraphListener类继承了MouseListener和MouseMotionListener来实现鼠标监听和鼠标拖动监听,关于鼠标系列的监听器,只要记住关键点就是,它用来监听容器类,时刻记住这点,你要用它监听什么,就把什么绑上这个监听器,因为我要实现的是在画布上作画,即我规定鼠标监听器的作用范围是画布,所以
//添加画布的鼠标监听器 WestGraphListener westGraphListener=new WestGraphListener(graphicsBrush,buttonGroupPen,jButtonPen,arrayList); jPanelDraw.addMouseListener(westGraphListener); jPanelDraw.addMouseMotionListener(westGraphListener);
其中传过去的参数这样来理解,我在监听器上我要用到的信息是什么。
1)我需要用到的重要信息自然是画笔,可以根据鼠标的动作在屏幕上留下痕迹的东西,因为鼠标的不断移动变化,自然不能将什么东西绑在鼠标上,所以GUI提供了一种画笔,你要在什么容器上面作画,你就从什么容器上获取画笔
//从画布获取画笔 Graphics graphicsBrush=jPanelDraw.getGraphics();
2)比如我想实现不同画笔的实现,那么我就要得到我所点击的西边区域那些画笔的信息,本来要得到那些画笔的信息,也应该在那些按钮上绑定监听器,但是因为按钮组有强大的可以获取到相应信息的功能
ButtonModel buttonModel=buttonGroupPen.getSelection(); command=buttonModel.getActionCommand();
所以就不需要绑定监听器了,直接把按钮组当做参数传给监听器就可以了,但是其他的实现还是需要单选按钮绑上监听器,这里先不说。
【】另一个SouthColorListener类继承了ActionListener类来实现事件监听,关于事件监听记住关键点,这是监听按钮组件的,前面说过因为单选按钮的按钮组有强大的获取单选按钮的事件信息,不过也可以给单选按钮绑上事件监听器来实现其他的动作,比如下面子面板(各个画笔的粗细的选项面板)的切换。
嗯,南边区域的颜料盘也是一个个按钮组成的,所以要实现颜色的切换,就可以给这些按钮绑上事件监听器
SouthColorListener southColorListener=new SouthColorListener(jButtonPen); //以及写在循环里的绑定 jButtonPigment.addActionListener(southColorListener);
这个事件监听器的实现代码比较少
public class SouthColorListener implements ActionListener{ public JButton jButtonPen; public SouthColorListener(JButton jButtonPen) { this.jButtonPen=jButtonPen; } public void actionPerformed(ActionEvent e) { //获取事件源 JButton jButtonPigment=(JButton)e.getSource(); Color color=jButtonPigment.getBackground(); jButtonPen.setBackground(color); } }
(三)各种画笔功能的实现
数一下,可以发现我们的西边区域的画笔有16个格子,即16种画笔要实现,可以用if else来进行画笔的选择,不急,可以先把画笔划分到几个不同的鼠标监听里
1)先是MouseListener类的mouseReleased方法,在这方法里,什么图形是在鼠标释放的瞬间形成的?直线,矩形,椭圆,圆矩形还有取色的功能,至于具体的实现,可以查阅API中graphics类下的各种方法实现,在下一章博客我也会把完整的代码贴出来。
不过可以说一下其中取色器的实现,取色器里用到了robot机器人类,做到自动获取屏幕中信息的功能,用机器人类可以实现远程监听呢。
if (command.equals("jpg-4")) { //取色器的实现 try { Robot robot=new Robot(); //截屏 //创建一个矩形区域对象 Rectangle rectangle=new Rectangle(e.getXOnScreen(), e.getYOnScreen(), 1, 1); BufferedImage bufferedImage=robot.createScreenCapture(rectangle); //获取图片像素点的颜色 int c=bufferedImage.getRGB(0, 0); Color color=new Color(c); //把颜色设置到颜料盘的JButtonPen上 jButtonPen.setBackground(color); } catch (AWTException e1) { e1.printStackTrace(); } }
2)然后是MouseMotionListener类的mouseDragged(拖动)方法,什么图形是鼠标一边拖动一边形成的呢?橡皮擦,铅笔,刷子,喷枪。
这几个图形用到的方法其实都是画直线的方法,只是比画直线多了一些技巧,比如喷枪的实现:
if (command.equals("jpg-8")) { //绘制喷枪 graphicsBrush.drawLine(x2, y2, x2, y2); //在当前点周围绘制更多的随机点 for (int i = 0; i < 30; i++) { int x_p=random.nextInt(21)-10; int y_p=random.nextInt(21)-10; 4000 graphicsBrush.drawLine(x2+x_p, y2+y_p, x2+x_p, y2+y_p); } }
(四)不算最后的实现:重绘
重绘的原理即是重写JFrame类里的paint方法,我们计算机的存储有三种,硬盘,内存,闪存(CPU)。内存存电脑正在运行的数据,闪存存屏幕上出现的数据。你创建的窗体对象,缩小了再放大,关于它的属性大小标题什么的原封不动的重现在屏幕上,但你在这个窗体对象上画的画,没有重现,为什么?因为你创建的窗体是对象,内存存了它的数据,但你画的东西都只是临时的,内存并没有存下,所以CPU没法从内存里得到你画下的东西的数据,然后再重现在屏幕上。
你重写一个继承JFrame类里的paint方法:
//画布设置 JPanel jPanelDraw=new JPanel() { //重绘功能 public void paint(Graphics graphicsBrush) { super.paint(graphicsBrush); for (int i = 0; i < arrayList.size(); i++) { //获取对象 MyShape myShape =arrayList.get(i); myShape.draw(graphicsBrush); } } };
为什么要把paint方法放在画布里?因为你重绘要用到的画笔应该是来自画布的,保持了作画和重绘的一致性。
自然,要存。用什么存?
//创建全局数组队列 ArrayList<MyShape> arrayList=new ArrayList<MyShape>();
用数组队列来存,存下一个个被封装了的图形对象MyShape,然后调用MyShape里的draw方法,将一个个对象重新画出来。在MyShape类里面,封装好一个个图形要用到的坐标数据和颜色以及画笔的粗细。
public abstract class MyShape { public int x1,x2,y1,y2,size; public Color color; public MyShape(int x1, int x2, int y1, int y2,Color color) { this.x1=x1; this.x2=x2; this.y1=y1; this.y2=y2; this.color=color; } public MyShape(int x1, int x2, int y1, int y2, Color color, int size) { this.x1=x1; this.x2=x2; this.y1=y1; this.y2=y2; this.color=color; this.size=size; } public abstract void draw(Graphics graphicsBrush); }
再用一个个子类来继承这个抽象类,来实现各种图形的绘制和重绘,做到封装的效果,比如直线类:
public class MyLine extends MyShape{ public MyLine(int x1, int x2, int y1, int y2, Color color) { super(x1, x2, y1, y2,color); } public MyLine(int x1, int x2, int y1, int y2, Color color, int size) { super(x1, x2, y1, y2, color, size); } public void draw(Graphics graphicsBrush) { graphicsBrush.setColor(color); ((Graphics2D) graphicsBrush).setStroke(new BasicStroke(size)); graphicsBrush.drawLine(x1, y1, x2, y2); } }
整体的画板实现思路就是这样了,画板->监听->多图形实现->重绘。完整的代码在下一章贴出来,总共有九个类,类多不要紧,只要业务实现逻辑对就行。
相关文章推荐
- java应用——高仿XP画板(四:整个代码)
- java应用——高仿XP画板(二:实现部分监听)
- 为你的Java应用嵌入一个功能强大的文字编辑器
- 【AS3代码】小画板升级版(带重绘回放和清空功能)
- 黑马程序员-9-java-IO流知识点串讲(3)-IO修饰(功能扩展)类及其应用
- Java应用——高仿Windows XP画板(一)
- 在应用中加入全文检索功能—基于Java的全文索引引擎Lucene简介(收藏)
- 开发整理-Javaweb应用的系统升级功能
- Java小程序之自定义数组队列的实现(高级画板重绘基础)
- java中组合的应用(不相干的类共同完成一个功能)+构造器回顾
- spring,springMVC的优点和区别 spring 是是一个开源框架,是为了解决企业应用程序开发,功能如下 ◆目的:解决企业应用开发的复杂性 ◆功能:使用基本的JavaBean代替EJB,并
- 学习java第6天 模仿XP画板(10%)
- Java小程序之高级画板功能篇II
- [转]在应用中加入全文检索功能(基于Java的全文索引引擎Lucene简介)
- Java Robot应用示例之机器人功能
- 在应用中加入全文检索功能——基于Java的全文索引引擎Lucene简介 [摘]
- Java 正则表达式功能及应用
- 给domino应用加上验证码功能
- 从HAL层到java应用层重写mini6410 led功能
- 在应用中加入全文检索功能——基于Java的全文索引引擎Lucene简介