疯狂java实战演义第6章 仿Windows画图Word文件下载.docx
《疯狂java实战演义第6章 仿Windows画图Word文件下载.docx》由会员分享,可在线阅读,更多相关《疯狂java实战演义第6章 仿Windows画图Word文件下载.docx(38页珍藏版)》请在冰豆网上搜索。
使用Windows的画图软件,发现在编辑图片的时候,有个相似的过程,首先是用鼠标选择需要使用的工具,然后就在画板中用鼠标进行拖动、点击等动作,画板会显示出相应工具的所产生的效果,所以在这里设计一个命名为Tool的接口,这个接口是所有工具的接口,里面定义了一系列的鼠标动作。
实际上在这个画图工具中,所有的工具都必须遵守一定的规范,即使用鼠标进行拖动、点击等动作,当需要定义某些规范的时候,我们可以将这些规范写到一个接口中,那么这个接口所有的实现类都要遵守这个规范,这也是本章将工具作为一个接口的原因。
在本章中,画图软件的主界面使用ImageFrame,该类继承于JFrame,该类会初始化画图软件的各种组件。
由于我们有选择打开图片文件的操作,所以会有一个扩展javax.swing.JFileChooser类(为选择文件提供一种简单的窗口选择机制)的ImageFileChooser类,用于处理选择文件时的过滤等操作。
因为绘图的功能已经全部由Tool的实现类去实现,所以除了绘图外的其它功能的逻辑实现,就全部放到ImageService类中,本章中的类图如图6.2所示。
图6.2画图软件类图
6.3.1工具接口Tool
从图6.2中可以看到,工具接口Tool定义了鼠标动作的四个方法,分别是拖动mouseDrapped()、移动mouseMoved()、松开mouseReleased()、按下mousePressed()、点击mouseClicked()五个动作,并用String类型的常量属性来定义工具的类型。
这个接口只有一个实现类AbstractTool,而每个工具类都是去扩展AbstractTool类,在图中表现为Tool1、Tool2…….ToolN。
以下是此接口定义的属性与方法:
❑staticfinalStringARROW_TOOL,箭头工具类型。
❑staticfinalStringPENCIL_TOOL,铅笔工具类型。
❑staticfinalStringBRUSH_TOOL,刷子工具类型。
❑staticfinalStringCUT_TOOL,剪切工具类型。
❑staticfinalStringERASER_TOOL,橡皮擦工具类型。
❑staticfinalStringLINE_TOOL,直线工具类型。
❑staticfinalStringRECT_TOOL,矩形工具类型。
❑staticfinalStringPOLYGON_TOOL,多边形工具类型。
❑staticfinalStringROUND_TOOL,椭圆形工具类型。
❑staticfinalStringROUNDRECT_TOOL,圆角矩形工具类型。
❑staticfinalStringATOMIZER_TOOL,喷墨工具类型。
❑staticfinalStringCOLORPICKED_TOOL,颜色选择工具类型。
❑voidmouseDragged(MouseEvente),当捕捉到鼠标拖动时调用的方法定义。
❑voidmouseMovedMouseEvente),当捕捉到鼠标移动时调用的方法定义。
❑voidmouseReleasedMouseEvente),当捕捉到鼠标松开时调用的方法定义。
❑voidmousePressedMouseEvente),当捕捉到鼠标按下时调用的方法定义。
❑voidmouseClickedMouseEvente),当捕捉到鼠标点击时调用的方法定义。
从接口中定义的属性与方法可以看出,在接口中只定义工具的类型,还有定义工具鼠标动作的方法,就不再做任何的事情,这些方法由它的实现类去具体实现。
在某个对象中需要使用到Tool的实现类时,我们可以使用一个ToolFactor的类来得到具体的某个Tool实现类,ToolFactory返回的都是Tool接口,因此使用者根本不需要关心使用的是哪一个实现类,当代码发生改变的时候,也可以减少代码的修改。
换言之,使用者只与ToolFactory耦合。
6.3.2Tool的实现类AbstractTool
AbstractTool是Tool的实现类,也是一个抽像类,所以并不能被创建,只能被继承。
此类实现Tool中定义的所有方法,并扩展了其它方法,让其子类继承或者重写。
该类中为其他的工具类提供了大部分的实现,那么它的子类就可以不必再做重复的实现,只关心与本类相关的逻辑,AbstractTool所定义的方法如下:
❑AbstractTool(ImageFrameframe),让子类调用的构造器,以ImagerFrame为参数,用于获取画板的属性。
❑AbstractTool(ImageFrameframe,Stringpath),让子类调用的构造器,以ImagerFrame为参数,path是工具的图标路径。
❑CursorgetDefaultCursor(),此方法获取默认鼠标指针的形状。
❑voidsetDefaultCursor(Cursorcursor),设置鼠标指针指针,以Cursor为参数。
❑voidsetPressX(intx),设置鼠标按下的x坐标,int类型的x为鼠标的x坐标。
❑voidsetPressY(inty),设置鼠标按下的y坐标,int类型的y为鼠标的y坐标。
❑intgetPressX(),返回上次鼠标按下的x坐标。
❑intgetPressY(),返回上次鼠标按下的y坐标。
❑voidmouseDragged(MouseEvente),实现当捕捉到鼠标拖动时调用的方法。
❑voidmouseMovedMouseEvente),实现当捕捉到鼠标移动时调用的方法。
❑voidmouseReleasedMouseEvente),实现当捕捉到鼠标松开时调用的方法。
❑voidmousePressedMouseEvente),实现当捕捉到鼠标按下时调用的方法。
❑voidmouseClickedMouseEvente),实现当捕捉到鼠标点击时调用的方法。
❑voidcreateShape(MouseEvente,Graphicsg),画图形,通过参数e去获取鼠标的轨迹,并用Graphics类型的对象g去画图形。
❑voiddraw(Graphicsg,intx1,inty1,intx2,inty2),画图形,g是用来画图形的对象,(x1,y1)是起点坐标,(x2,y2)是终点坐标。
这个方法是一个空的方法,主要是由其子类实现。
❑voiddragBorder(MouseEvente),拖动边界,也就是改变画布的大小。
接口用于定义规范,那么抽象类就是用于实现部分的规范。
当我们在编写程序的过程中发现,有一类对象都必须遵守某些行为,那么我们可以将这些行为都当作规范,写到接口中;
如果有些对象实现了部分的行为,其他的行为更希望让它的子类去实现,那么我们可以将这些对象作为一个抽象类。
6.3.3AbstractTool的子类
AbstractTool一共有ArrowTool(箭头)、PencilTool(铅笔)、BrushTool(刷子)、EraserTool(橡皮擦)、LineTool(直线)、RectTool(矩形)、PolygonTool(多边形)、RoundTool(椭圆形)、RoundRectTool(圆矩形)、AtomizerTool(喷墨)、ColorPickedTool(颜色选择)11个子类,这些子类都是根据自己的情况重写AbstractTool的部分或者全部方法。
由于在本设计中,想这些类在外表现为Tool接口,不希望被直接实例化,所以此类的构造器私有,并提供一个静态的方法获取Tool类型的此类实现,如下:
❑staticToolgetInstance(ImageFrameframe),获取Tool类型的本类实例。
由于我们并不希望外界可以直接使用new关键字来创建这些类的实例,因此在这里使用了单态模式,所有的子类都提供了getInstance的方法来返回本类的实例,并且所有的构造器都是私有的。
在下面的章节中,将会讲解如何实现这11个子类。
6.3.4界面类ImageFrame
这个画图工具的界面的主要放在这个类中实现,此类有以下方法:
❑voidinit(),设置化主界面。
❑JPanelgetDrawSpace(),获取画布。
❑JPanelgetColorPanel(),获取颜色面板。
❑MyImagegetBufferedImage(),获取画板中的图片。
❑voidsetBufferedImage(MyImagebufferedImage),设置画板图片,MyImage是BufferedImage的一个扩展类。
❑voidsetTool(Tooltool),设置正在使用的工具。
❑ToolgetTool(),获取正在使用的工具。
❑JColorChoosergetColorChooser(),获取颜色选择器。
❑JPanelcreateColorPanel(),创建一个简单的颜色选择面板。
❑JPanelgetCurrentColorPanel(),获取颜色选择面板。
❑DimensiongetScreenSize(),获取Dimension类形screenSize,screenSize主要用于获取画板的高与宽等属性。
❑voidcreateMenuBar(),创建文件、查看、颜色、帮助等菜单栏。
❑JPanelcreateDrawSpace(),创建画板。
❑JPanelcreateToolPanel(),创建用于画图的工具栏。
另外,此类有一个继承JPanel的内部类DrawSpace,用于充当画图工具的画板,此内部类只有一个方法,就是一个用于绘图的方法,如下:
❑voidpaint(Graphicsg),画图。
界面类类似于我们MVC模式中的V(视图),该类并不负责处理任何的逻辑,主要负责从界面接收数据,再传递给具体的业务类,让其进行相关的处理。
在本章,负责处理画图功能的主要是Tool的实现类。
6.3.5业务逻辑类ImageService
除鼠标的画图功能外(画图功能由Tool的实现类完成),初始化画板、图片的新建打开与保存、各种面板的显示与隐藏、颜色的编辑、整个界面的刷新、菜单等业务逻辑都放在这个类中实现,该类包含了以下的方法:
❑initDrawSpace(ImageFrameframe),初始化画板。
❑DimensiongetScreenSize(),获取屏幕的分辨率。
❑repaint(Graphicsg,BufferedImagebufferedImage),刷新界面。
❑staticCursorcreateCursor(Stringpath),创建鼠标图形。
Path是鼠标图形的路径。
❑voidsave(booleanb,ImageFrameframe),保存图片。
❑voidopen(ImageFrameframe),打开图片。
❑voidcreateGraphics(ImageFrameframe),创建新图片并初始化。
❑voideditColor(ImageFrameframe),编辑颜色。
❑voidexit(ImageFrameframe),退出画图软件。
❑voidmenuDo(ImageFrameframe,Stringcmd),处理菜单事件。
除了画图功能外,ImageService负责了整个画图工具的其他功能,在本章中,该类是无状态的Java对象,它并没有保存一些状态属性。
6.3.6文件选择类ImageFileChooser
ImageFileChooser类继承了JFleChooser类,JFleChooser是Java提供的一个简单的文件选择机制,我们这里扩展这个类,是为了增加我们自己的文件过滤器。
见以下方法:
❑StringgetSuf(),获取文件的后缀名。
❑voidaddFilter(),增加文件过滤器,这里只选择图片类形的文件。
这个类中有一个继承FileFilter类的内部类MyFileFilter,这个内部类主要是重写FileFilter的accept方法,判断是否是合法的文件类型,如下:
❑booleanaccept(Filef),判断是否是合法的文件类型。
在本小节中,我们主要确定了画图工具所涉及的几个对象,并定义了他们的行为与属性,在下面章节中,我们只要按照这些定义好的方法,逐步去实现我们的画图工具。
6.4主界面实现
在这个软件中,主界面主要由左边的工具栏、下面的颜色选择板、占大部分区域的画图区、菜单等几部分组成,用BorderLayou的排板方式,左边工具栏在BorderLayou.WEST位置,画图区在BorderLayout.CENTER位置,颜色选择面板在BorderLayout.SOUTH位置。
先看主界面的初始化:
6.4.1初始化界面(init()方法)
首先,设置JFrame窗口的标题,接下来初始化画图区域,初始化为白色,然后再获取PENCIL_TOOL(铅笔)类型的Tool,创建各种鼠标监听器,并在监听的执行方法中调用Tool的相应方法,最后获取左边工具栏面板、下面菜单栏面板、菜单,并把这些面板与画图获取加到JFrame中。
见以下代码。
代码清单:
code\image\src\org\crazyit\image\ImageFrame.java
publicvoidinit(){
//设置标题
this.setTitle("
未命名-画图"
);
//初始化画图
service.initDrawSpace(this);
//获取正在使用的工具
tool=ToolFactory.getToolInstance(this,PENCIL_TOOL);
//创建鼠标运动监听器
MouseMotionListenermotionListener=newMouseMotionAdapter(){
//拖动鼠标
publicvoidmouseDragged(MouseEvente){
tool.mouseDragged(e);
}
//移动鼠标
publicvoidmouseMoved(MouseEvente){
tool.mouseMoved(e);
};
//创建鼠标监听器
MouseListenermouseListener=newMouseAdapter(){
//松开鼠标
publicvoidmouseReleased(MouseEvente){
tool.mouseReleased(e);
//按下鼠标
publicvoidmousePressed(MouseEvente){
tool.mousePressed(e);
//点击鼠标
publicvoidmouseClicked(MouseEvente){
tool.mouseClicked(e);
drawSpace.addMouseMotionListener(motionListener);
drawSpace.addMouseListener(mouseListener);
createMenuBar();
//以drawSpace为viewport去创建一个JScrollPane
scroll=newJScrollPane(drawSpace);
//设置viewport
ImageService.setViewport(scroll,drawSpace
bufferedImage.getWidth(),bufferedImage.getHeight());
//将panel加到本Frame上面
this.add(scroll,BorderLayout.CENTER);
//this.add(toolPanel,BorderLayout.WEST);
//this.add(colorPanel,BorderLayout.SOUTH);
}
可以看到,这里有两种鼠标监听器,MouseMotionListener和MouseListener,MouseMotionListener主要是监听鼠标的运动动作,我们实现了它的mouseDragger(鼠标拖动)与mouseMoved(鼠标移动)方法,MouseListener负责监听鼠标的其它动作,我们实现了它的mouseReleased(松开鼠标)、mousePressed(按下鼠标)和mouseClicked(点击鼠标)三个方法。
以上代码的黑体部分,这三行代码分别创建菜单、画图工具栏与颜色选择面板,如何创建我们将在6.4.3、6.4.4和6.4.5中详细描述。
现在运行画图工具,可以看到效果如图6.3所示。
图6.3主界面
6.4.2获取画板
这是一个画图工具,所以需要一个可以绘图的区域,在这里我们用继承JPanel的内部类DrawSpace去充当这个绘图区域,见以下代码。
//画图区域
publicclassDrawSpaceextendsJPanel{
/**
*重写voidpaint(Graphicsg)方法
*
*@paramgGraphics
*@returnvoid
*/
publicvoidpaint(Graphicsg){
//draw
service.repaint(g,bufferedImage);
}
从上面代码可以看到,这个内部类比较简单,只是继承JPanel,并重写JPanel的paint方法,这里需要注意的是,要调用此方法,并不是直接调用paint方法,而是调用ImageService的repaint方法。
而获取这个画板就是去创建一个这个画板类的实例,由于我们的画图软件是每次都只编辑一张图片,所以这个创建画板的方法在本类中只被调用一次。
首先是new一个DrawSpace实例,再设置这个drwaSpace的大小,并且返回,见以下代码。
//创建画板
publicJPanelcreateDrawSpace(){
JPaneldrawSpace=newDrawSpace();
//设置drawSpace的大小
drawSpace.setPreferredSize(
newDimension((int)screenSize.getWidth()
(int)screenSize.getHeight()-150));
returndrawSpace;
}
6.4.3创建菜单
这个软件的菜单组织形式如下:
-文件(F)
-新建(N)
-打开(O)
-保存(S)
-退出(X)
-查看(V)
-工具箱(T)
-颜料盒(C)
-颜色(C)
编辑颜色
-帮助(H)
-帮助主题
-关于
由于菜单比较简单,我们把文件、查看、颜色、帮助四个菜单文字放在一个String类型的数组menuArr里面,并迭代这个数组去创建一个JMenu,JMenu就是指菜单。
同样,把他们下面的各个菜单项文字也放在一个String类型的二维数组里面,去迭代创建每个JmenuItem(菜单项),每创建完一个,就为它加上一个动作监听器,去监听这个菜单项是否被点击。
请看以下代码。
//创建菜单
publicvoidcre