博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java应用——高仿XP画板(三:加上重绘功能)
阅读量:3976 次
发布时间:2019-05-24

本文共 4501 字,大约阅读时间需要 15 分钟。

XP画板到今天可以说已经基本实现完毕,出了菜单栏部分的功能。不过我写的代码在实现部分依然有一点缺陷,我会继续更新这篇博客,来完善功能。

首先,从一个大体上来叙述整个代码的实现。
(一)一个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;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
arrayList=new ArrayList
();

用数组队列来存,存下一个个被封装了的图形对象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);}}

整体的画板实现思路就是这样了,画板->监听->多图形实现->重绘。完整的代码在下一章贴出来,总共有九个类,类多不要紧,只要业务实现逻辑对就行。

转载地址:http://birki.baihongyu.com/

你可能感兴趣的文章
linux下源码安装zbar
查看>>
Python 的生成二维码生成库 -- qrcode
查看>>
odoo教程---在odoo8中创建自定义的reports
查看>>
"go back" step in a workflow stops everything
查看>>
如何成为一名黑客
查看>>
英语学习资源收藏
查看>>
ubuntu下如何安装NFS服务用于文件共享
查看>>
VMware中Ubuntu安装VMware Tools步骤及问题解决方法
查看>>
优化VMware提高虚拟机运行速度的技巧
查看>>
gcc编译器命令使用详解
查看>>
gcc编译动态库和静态库的详细说明
查看>>
linux下用gcc生成静态库和动态库
查看>>
linux下的动态库和静态库
查看>>
linux的ar命令---创建静态库
查看>>
js判断MAC地址
查看>>
一亿用户增长背后的架构秘密 之 腾讯微信技术架构
查看>>
如何定义变长的TLV结构体?
查看>>
单表60亿记录等大数据场景的MySQL优化和运维之道 | 高可用架构
查看>>
MySQL Replication 常用架构
查看>>
php生成PDF文件(FPDF)
查看>>