疯狂java实战演义第3章 图片浏览器Word下载.docx
《疯狂java实战演义第3章 图片浏览器Word下载.docx》由会员分享,可在线阅读,更多相关《疯狂java实战演义第3章 图片浏览器Word下载.docx(19页珍藏版)》请在冰豆网上搜索。
.BMP"
},
"
BMP(*.BMP)"
));
在文件对话框的addFilter方法加入以上的代码后,那么用户将不能看到.bmp的文件,并且在“文件类型”的下拉中也只能选择.bmp,效果如图3.3所示。
在本章中,文件对话框对应的是ViewerFileChooser类。
图3.3文件过滤器的作用
3.2.3主界面类
我们建立一个界面类作为图片浏览器的主界面,该类包括图片显示区、菜单栏、工具栏,并为工具栏与菜单栏加上事件监听器,如下:
❑voidinit(),初始化图片浏览器的界面。
❑JLabelgetLabel(),获取显示图片的JLabel。
❑createToolPanel(),创建放大、缩小、上一张、下一张等工具按钮。
❑voidcreateMenuBar(),创建文件、工具、帮助等菜单。
在这里需要注意的是,由于打开的图片大小并不能确定,因此图片显示区必须使用JScrollPane。
在本章中,主界面对应的是ViewerFrame类。
3.2.4业务处理类ViewerService
业务处理类主要是处理图片浏览器的大部分业务逻辑,包括打开图片、关闭浏览器、放大图片、缩小图片、浏览上一张图片、浏览下一张图片等功能,如下:
❑staticViewerServicegetInstance(),获取ViewerService类的一个单态实例。
❑voidopen(ViewerFrameframe),弹出文件选择框,并读取被选择到的图片。
❑voidzoom(ViewerFrameframe,booleanisEnlarge),对正在浏览到的图片做放大或者缩小操作,这里可能会丢失图片精度。
❑voidlast(ViewerFrameframe),浏览上一张图片。
❑next(ViewerFrameframe),浏览下一张图片。
❑voidmenuDo(ViewerFrameframe,Stringcmd),响应菜单的动作。
在本章中,这个业务处理类并不是无状态的Java对象,也就是意味着本章的业务处理类将人保存一些业务状态,这些业务状态包括:
当前浏览的文件目录、文件目录的文件集合、图片放大或者缩小的比例等属性。
由于我们这个是有状态的Java对象,那么就意味着,如果访问的是同一个实例,那么该对象的这些属性将会被所有的访问者共享,如果其中的一个访问者改变了其中一个或者多个属性,那么其他的访问者将会受到影响。
当然,我们本章只是一个普通的图片浏览器,不存在多个用户使用同一个图片浏览器的情况。
在本章中,业务处理类对应的是ViewerService类。
3.2.5操作处理类
在本例中,由于用户可以执行的操作较少,因此,我们可以提供一个操作处理类来接收用户所有的操作,本例中的操作处理类是AbstractAction的一个子类,能用ImageIcon(图标)来创建一个Action,再用这个Action来创建按钮,点击按钮的时候,将调用此类的actionPerformed方法:
❑voidactionPerformed(ActionEvente),重写AbstractAction的方法,响应事件。
由于我们只有一个操作处理类,因此在实现actionPerformed方法时,我们就需要进行一系列的判断,让程序知道用户进行了何种操作,再调用业务处理类中的相应方法。
到此,图片浏览器的相关对象都已经建立,并且确定了我们需要实现哪些方法,我们在实现的过程中,如果发现可以对程序进行重构,那么也可以在重构的过程中,创建相关的类。
3.3创建主界面
这个图片浏览器的界面排版比较简单,只有菜单(不需要排版)、工具栏、图片显示区,我们使用BorderLayout进行布局,把工具栏放在BorderLayout.NORTH,把图片显示区放在BorderLayout.CENTER。
在本章中,由于打开图片的大小并不确定,因此我们需要使用一个JScrollPane来作为图片显示区域。
3.3.1初始化界面(init()方法)
首先,设置JFrame窗口的标题,接下来初始化画图区域,初始化为白色,然后再获取PENCIL_TOOL(铅笔)类型的Tool,创建各种鼠标监听器,并在监听的执行方法中调用Tool的相应方法,最后获取左边工具栏面板、下面菜单栏面板、菜单,并把这些面板与画图获取加到JFrame中,见以下代码。
代码清单:
code\viewer\src\org\crazyit\viewer\ViewerFrame.java
publicvoidinit(){
//设置标题
this.setTitle("
看图程序"
);
//设置大小
this.setPreferredSize(newDimension(width,height));
//创建菜单
createMenuBar();
//创建工具栏
JPaneltoolBar=createToolPanel();
//把工具栏和读图区加到JFrame里面
this.add(toolBar,BorderLayout.NORTH);
this.add(newJScrollPane(label),BorderLayout.CENTER);
//设置为可见
this.setVisible(true);
this.pack();
}
首先是为JFrame设置标题,接下来设置大小,然后调用本类的createMenuBar()方法去创建菜单栏、调用createToolPanel()方法去创建工具栏,最后把菜单栏和图片显示区加到JFrame中(图片显示区只是一个JLabel)。
以上代码中的黑体部分,使用一个createToolPanel的方法来创建菜单,该方法将在下面章节中实现。
3.3.2创建菜单栏
菜单栏,必须有事件响应,所以,先为菜单定义一个事件监听器,见以下代码。
//加给菜单的事件监听器
ActionListenermenuListener=newActionListener(){
publicvoidactionPerformed(ActionEvente){
service.menuDo(ImageFrame.this,e.getActionCommand());
}
};
这个事件监听器实现了ActionListener中的actionPerformed方法,是响应用户操作的方法,方法里面的service类就是我们的业务逻辑处理类ImageService的一个单态实例。
有了这个事件监听器,就可以一次性创建出所有的菜单(用数组定义好菜单文字等东西的形式),见以下方法。
publicvoidcreateMenuBar(){
//创建一个JMenuBar放置菜单
JMenuBarmenuBar=newJMenuBar();
//菜单文字数组,以下面的menuItemArr一一对应
String[]menuArr={"
文件(F)"
"
工具(T)"
帮助(H)"
//菜单项文字数组
String[][]menuItemArr={
{"
打开(O)"
"
-"
退出(X)"
},
放大(M)"
缩小(O)"
上一个(X)"
下一个(P)"
},
{"
帮助主题"
关于"
};
//遍历menuArr与menuItemArr去创建菜单
for(inti=0;
i<
menuArr.length;
i++){
//新建一个JMenu菜单
JMenumenu=newJMenu(menuArr[i]);
for(intj=0;
j<
menuItemArr[i].length;
j++){
//如果menuItemArr[i][j]等于"
if(menuItemArr[i][j].equals("
)){
//设置菜单分隔
menu.addSeparator();
}else{
//新建一个JMenuItem菜单项
JMenuItemmenuItem=newJMenuItem(menuItemArr[i][j]);
menuItem.addActionListener(menuListener);
//把菜单项加到JMenu菜单里面
menu.add(menuItem);
}
}
//把菜单加到JMenuBar上
menuBar.add(menu);
//设置JMenubar
this.setJMenuBar(menuBar);
图片浏览器的菜单是这样的结构:
文件(F)
打开(O)
退出(X)
工具(T)
放大(M)
缩小(O)
上一个(X)
下一个(P)
帮助(H)
帮助主题
关于
从代码中可以看到,程序用两个数组把这两层菜单的文字保存了进去,两个数组一起遍历,每次都创建一个菜单项(JMenuItem),并为这个菜单项增加上前面定义的事件监听器,然后把这个菜单项加到JMenu中。
每次遍历完
第一个数组,都把这个JMenu加到JMenuBar中。
遍历完所有数组,就把这个JmenuBar加到JFrame里面,创建菜单的过程就完成了。
3.3.3创建工具栏
这里的工具按钮,为了美观,想用图片的方式创建JButton,这里就要用到AbstractAction,也就是我们扩展的ViewerAction类,首先是用ViewerAction的ViewrAction(ImageIconicon,Stringname,ViewerFrameframe)去创建一个ViewrAction,参数里面的icon对象就是从本地路径中读了图标的图标类,然后以这个ViewerAction对象为参数去创建一个JButton。
见以下代码。
publicJPanelcreateToolPanel(){
//创建一个JPanel
JPanelpanel=newJPanel();
//创建一个标题为"
工具"
的工具栏
JToolBartoolBar=newJToolBar("
//设置为不可拖动
toolBar.setFloatable(false);
//设置布局方式
panel.setLayout(newFlowLayout(FlowLayout.LEFT));
//工具数组
String[]toolarr={"
open"
last"
next"
big"
small"
toolarr.length;
ViewerActionaction=newViewerAction(
newImageIcon("
img/"
+toolarr[i]+"
.gif"
)
toolarr[i],this);
//以图标创建一个新的button
JButtonbutton=newJButton(action);
//把button加到工具栏中
toolBar.add(button);
panel.add(toolBar);
//返回
returnpanel;
以上代码的黑体部分,我们使用了JButton来创建工具栏的图标,每一个JButton对象都使用ViewerAction作为构造参数,但是需要注意的是,各个JButton之间并不是共享一个ViewerAction的实例。
创建完菜单与工具栏后,可以运行查看具体的效果,主界面的效果如图3.4所示。
图3.4图片浏览器主界面
在本例中,图片浏览器的功能相对较为简单,因此界面也是较为简洁。
如果想做更强大的图片浏览器,可以参考ACESee或者Windows图片浏览器等功能。
3.4实现图片浏览的操作
ViewerService类主要是处理图片浏览器的大部分业务逻辑,包括打开图片、关闭浏览器、放大图片、缩小图片、浏览上一张图片、浏览下一张图片等功能,在这里需要再做一次说明,ViewerService是有状态的Java对象。
3.4.1实现工具栏点击
我们在3.2.5中创建了一个ViewerAction的类,主要用于处理工具栏的点击事件,当用户点击了工具栏的某个操作时,就会执行ViewerAction的actionPerformed的方法。
我们在3.3.3中创建工具栏时,使用了以下代码。
以上代码中使用了“open”、“last”等字符串用来标识应该使用ViewerService的哪个方法,那么就意味着我们需要在actionPerformed方法中作出这些判断:
if(this.name.equals("
)){
//打开文件对话框
}elseif(this.name.equals("
//上一下图片
…
本章中只有5个Action,就需要写5次的if…else,对于这样的代码,我们在本书的第二章(仿Windows计算器)中已经出现,当前并没有提供任何的解决方案,但是如果程序中出现如些之多的if…else,那么我们就需要想办法去解决。
接下来,创建一个Action的接口,提供一个execute的方法。
code\viewer\src\org\crazyit\viewer\action\Action.java
publicinterfaceAction{
/**
*具体执行的方法
*@paramservice图片浏览器的业务处理类
*@paramframe主界面对象
*/
voidexecute(ViewerServiceservice,ViewerFrameframe);
}
编写了接口Action后,我们定义了一个execute的方法,那么,我们可以为该Action新建实现类,例如有一个打开文件对话框的Action,那么我们就新建一个OpenAction,该类实现Action接口。
以下代码是OpenAction的具体的实现。
code\viewer\src\org\crazyit\viewer\action\OpenAction.java
publicvoidexecute(ViewerServiceservice,ViewerFrameframe){
//打开文件对话框
提供了这个OpenAction后,我们需要修改创建工具栏的代码,换一种方式创建工具栏。
//工具数组
org.crazyit.viewer.action.OpenAction"
org.crazyit.viewer.action.LastAction"
org.crazyit.viewer.action.NextAction"
org.crazyit.viewer.action.BigAction"
org.crazyit.viewer.action.SmallAction"
for(inti=0;
toolarr.length;
i++){
ViewerActionaction=newViewerAction(newImageIcon("
+toolarr[i]+"
),toolarr[i],this);
//以图标创建一个新的button
JButtonbutton=newJButton(action);
//把button加到工具栏中
将原来的字符串更换为某个Action实现类的全限定类名,那么在构造ViewerAction的时候,就可以使用这个参数去创建具体的某个实现类。
为ViewerAction编写一个工具方法,使用反射得到Action接口的某个实现类。
code\viewer\src\org\crazyit\viewer\ViewerAction.java
privateActiongetAction(StringactionName){
try{
if(this.action==null){
//创建Action实例
Actionaction=(Action)Class.forName(actionName).newInstance();
this.action=action;
returnthis.action;
}catch(Exceptione){
returnnull;
以上的黑体代码,使用了反射来创建一个实例,并且该实例在ViewerAction中只有一个实例,由于该方法在ViewerAction中,所以我们在构造ViewerAction的时候,将对应的处理类传入即可。
得到具体的某个Action实现类后,在实现ViewerAction的时候,我们就可以不必使用那堆烦人的if…else了,直接通过以上的工具方法(getAction)得到相关的Action实现类,再调用Action的execute方法即可。
publicvoidactionPerformed(ActionEvente){
ViewerServiceservice=ViewerService.getInstance();
Actionaction=getAction(this.actionName);
//调用Actio