亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

圖片瀏覽器--學習筆記(二)

系統 1622 0

接著上一部分,繼續分析開頭提出的幾個問題。

?

業務處理類(ViewerService)主要處理圖片瀏覽器的大部分業務邏輯,包括打開圖片、放大圖片、縮小圖片、瀏覽上一張圖片、瀏覽下一張圖片。


在這個類中使用了單態模式,即類內存中只能創建一個實例對象,將類的構造方法的訪問權限定義為private(于是無法在類的外部產生類的對象),在類的內部定義一個可以返回類的對象的方法,這個方法需要是靜態方法,(于是可以在類的外部調用該靜態方法返回類的對象),同時靜態方法只能訪問靜態變量,所以類內部產生的對象的變量也要是靜態的,代碼如下:

    //私有構造器
private ViewerService(){}
private static ViewerService service = new ViewerService();
//獲取單態實例
public static ViewerService getInstance() {
	return service;
}
  

這樣做的原因是該業務處理類的對象不是無狀態的JAVA對象,該類中定義了一些保存業務狀態的屬性,包括當前瀏覽的文件目錄、當前瀏覽的圖片文件、文件目錄的文件集合、圖

片放大和縮小的比例。如果訪問的是同一個實例,這些表示業務狀態的屬性就會被所有訪問者共享,其中一個訪問者改變了屬性的值,其他訪問者也會受到影響。
(對于這一部分,我也不是特別明白,盡量去理解吧,總會有豁然開朗的一天)

?

不管是菜單欄的菜單項還是工具欄的按鈕,都必須要有事件響應,這里有兩種實現方案。第一種,是初學者比較容易想到的,直接為菜單定義一個事件監聽器,代碼如下:

    //為菜單定義事件監聽器
	ActionListener menuListener= new ActionListener(){
		public void actionPerformed(ActionEvent e){
service.menuDo(ViewerFrame.this,e.getActionCommand());
		}
	};
//新建一個菜單項,并注冊事件監聽器
JMenuItem menuItem = new JMenuItem(MenuItemArr[i][j]);
menuItem.addActionListener(getActionListener());

這樣的方法會帶來一系列的if…else,請看代碼:
	//實現菜單的單擊
	public void menuDo(ViewerFrame frame, String cmd) {
		//打開
		if(cmd.equals("打開(O)")){
			open(frame);
		}
		//放大
		if(cmd.equals("放大(M)")){
			zoom(frame,true);
		}
		//縮小
		if(cmd.equals("縮小(O)")){
			zoom(frame,false);
		}
		//上一個
		if(cmd.equals("上一個(X)")){
			last(frame);
		}
		//下一個
		if(cmd.equals("下一個(P)")){
			next(frame);
		}
		//退出
		if(cmd.equals("退出(X)")){
			System.exit(0);
		}				
	}
  

下面看第二種實現方式,以工具欄上的按鈕的事件響應為例。
在看第二種實現方式之前,先用第一種方式來實現:
與菜單實現不同的是,這里創建一個ViewerAction類,在這個類中定義事件監聽器。

    String[] toolarr = {"open","last","next","big","small"};
for(int i = 0;i<toolarr.length;i++){
	ViewerAction action = new ViewerAction(
new ImageIcon("img/"+ toolarr[i]+ ".gif", toolarr[i],this)
);
        //以圖標創建一個新的button
        JButton button = new JButton( action );
        //把button加入到工具條中
        toolbar.add(button);
}
  

使用了"open","last","next","big","small"等字符串來標識應該使用ViewerService的哪些方法,這意味著我們需要在actionPerformed方法中來做這些判斷。

    public class ViewerAction extends AbstractAction {

	String name =null;
	ViewerFrame frame = null;
	public ViewerAction(ImageIcon icon, String name, ViewerFrame frame) {
		super(name,icon);
		this.name = name; 
		this.frame = frame;
	}
	public void actionPerformed(ActionEvent e) {
		if(this.name.equals("open")){
			//在這里調用打開文件對話框的方法
		}else if(this.name.equals("last")){
			//在這里調用上一張圖片的方法
		} else if(this.name.equals("next")){
			//在這里調用下一張圖片的方法
		} else if(this.name.equals("big")){
			//在這里調用放大圖片的方法
		} else if(this.name.equals("small")){
			//在這里調用縮小圖片的方法
		}
	}
}
  

下面使用另一種方法,可以避免這些if… else語句。
先是創建一個Action接口,提供一個execute方法。這一步用到了命令模式:



接下來為Action接口新建實現類,



在創建工具欄上的按鈕時,將原來的字符串更換成實現類的全限定名:

    String [] toolarr = {"org.crazyit.viewer.OpenAction",
				"org.crazyit.viewer.LastAction","org.crazyit.viewer.NextAction",
				"org.crazyit.viewer.BigAction","org.crazyit.viewer.SmallAction"};
		String [] toolimg = {"open","last","next","big","small"};
		for(int i=0;i<toolarr.length;i++){
			
			//為了美觀,想用圖片的方式創建JButton
			ViewerAction action = new ViewerAction(new ImageIcon("images/"+toolimg[i]+".png"),toolarr[i],this);
			//為工具欄創建按鈕
			JButton button = new JButton(action); 
			button.setHideActionText(true);
			//默認情況下對圖片的操作按鈕不可用
			if(i!=0){
				button.setEnabled(false);
			}
			//將按鈕添加到工具欄上
			toolBar.add(button);
		}
  

那么在構造ViewerAction用這個參數來記錄下具體的某個實現類的類名,為ViewerAction編寫一個工具方法,使用反射得到某個實現類的一個實例:

    private Action getAction(String actionName) {
		try{
			if(this.action ==null){
				//創建Action實例
				Action action = (Action) Class.forName(actionName).newInstance();
				this.action = action;
			}
			return this.action;
		}catch(Exception ex){
			return null;
		}	
  

注意,使用反射來創建的實例是唯一的,在事件監聽器中使用該工具方法,返回該實例,并調用該實例的execute()方法。
用這種方法就避免了大量的if…else,也具有一定的擴展性,使用了多態。

?

如何實現打開圖片?
如何放大或者縮小圖片?
如何實現瀏覽“上一張”或“下一張”圖片?

首先用ViewerFileChooser對象的showOpenDialog方法彈出一個文件選擇框,在用戶選擇了某個圖像文件后,點擊確定按鈕后,該方法會返回一個值APPROVE_OPTION。

這時需要把這個文件所在的文件夾中的所有圖像文件都緩存起來,這樣是為了不用每次都去搜索這個文件夾內的文件,也是為了方便“上一張”和“下一張”的定位,緩存的文件都保存在currentFiles中,它的類型是ArrayList<File>。這里還要考慮問題的是,在用戶第一次打開某個圖片文件后,它所在的文件夾中的文件被緩存到了currentFiles中,在用戶第二次打開某個圖片文件后,它所在的文件夾可能已經發生了變化,這時需要把新的文件夾中的所有文件緩存到currentFiles中,所以在每次用戶打開文件圖片時,都要判斷文件夾是否改變,如果改變了,要重新進行緩存:

    if(cd != this.currentDirectory || this.currentDirectory==null){
				//獲取fileChooser的所有FileFilter
				FileFilter [] fileFilters = fileChooser.getChoosableFileFilters();
				//獲取讀取到的文件
				File files[] = cd.listFiles();
				this.currentFiles = new ArrayList<File>();
				//將符合自定義過濾器的文件緩存下來
				for(File file : files){
					for(FileFilter filter: fileFilters){
						//如果是圖片文件
						if(filter.accept(file)){
							//把符合過濾器的文件加到currentFiles中
							this.currentFiles.add(file);
						}
					}
				}
}
  

如果文件路徑發生了變化,或者這是第一次打開文件,就執行if語句中的代碼。
對于圖片的放大或者縮小,使用了Image中的一個叫getScaledInstance的方法。

    ImageIcon newIcon = new ImageIcon(icon.getImage().getScaledInstance(width, -1, Image.SCALE_DEFAULT));
  

其中參數width表示將圖像縮放到的寬度,height表示將圖像縮放到的高度,hints表示指示用于圖像重新取樣的算法類型的標志,其實就是選擇一種縮放算法。
如果width或height為負數,則替換該值以維持初始圖像尺寸的高寬比。
對于取上一張或下一張圖片的方法就相對容易了,因為在打開文件的時候,已經把文件夾下的文件緩存在了currentFiles中,只需要獲得當前文件的索引,然后按照索引加1或索引減1來找到上一張文件或下一張文件。

圖片瀏覽器--學習筆記(二)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产一久久香蕉国产线看观看 | 激情午夜婷婷 | 1000部羞羞禁止免费观看视频 | 一级毛片一级毛片免费毛片 | 欧美精品久久久亚洲 | 韩国欧美一级毛片免费 | 欧美曰韩一区二区三区 | 国产精品嘿咻嘿咻在线播放 | 成人精品一区二区久久 | 女人zzzooooxxxx | 妖精视频永久在线入口 | 日韩性大片免费 | 成年网站视频在线观看 | jizz成熟丰满中国妇女 | 国产在线短视频 | 欧洲色综合精品 | 四虎影院的网址 | 曰本性l交片视频视频 | 四虎国产精品免费五月天 | 毛片机地 | 人人干人人爱 | a毛片免费| 久久天天躁狠狠躁夜夜躁 | 欧美日本免费观看αv片 | 亚洲国产精品一区二区久久 | 一区二区三区在线 | 欧 | 欧美成人精品欧美一级乱黄 | 越猛烈欧美xx00动态图免费 | 亚洲一级毛片 | 亚洲精品乱码久久久久久麻豆 | 四虎影院精品 | 日日干夜夜骑 | 精品国产一区二区三区在线观看 | 九热视频| 色天天综合久久久久综合片 | 九九热热九九 | 国产成人亚洲综合 | 欧美网站www| 亚洲综合视频网 | 99re6在线视频免费精品 | 四虎免费大片aⅴ入口 |