国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

Eclipse 向?qū)C制擴展 -- 實現(xiàn)可定制的向?qū)?/h1>
2019-11-14 09:52:44
字體:
供稿:網(wǎng)友

實現(xiàn)動態(tài)頁數(shù)和樹狀拓?fù)浣Y(jié)構(gòu)的 Eclipse 向?qū)?/h1>

本文首先剖析了 Eclipse 向?qū)C制的實現(xiàn)原理,包括頁面的加載和注銷,頁面校驗,向?qū)?zhí)行流程,向?qū)繕?biāo)操作等。目前,Eclipse 向?qū)ы撁鎯?nèi)容是固定的,向?qū)б唤?jīng)創(chuàng)建,其內(nèi)容和順序就無法改變。然而,在現(xiàn)實世界中,我們面對的邏輯往往是復(fù)雜多變的,固定的順序的 Eclipse 向?qū)Ы?jīng)常無法滿足用戶需要,因而,文章從兩個方面對當(dāng)前 Eclipse 向?qū)C制進(jìn)行了擴展:具有動態(tài)頁數(shù)的 Eclipse 向?qū)б约皹錉钔負(fù)浣Y(jié)構(gòu)的 Eclipse 向?qū)АU展后的 Eclipse 向?qū)В梢院芊奖愕乇婚_發(fā)人員重用,進(jìn)而提高開發(fā)效率。

劉 力, 軟件工程師, EMC

杜 冰冰, 軟件工程師, IBM

2010 年 5 月 20 日

expand內(nèi)容

在 IBM Bluemix 云平臺上開發(fā)并部署您的下一個應(yīng)用。

引言

文章將對現(xiàn)有 Eclipse 向?qū)C制進(jìn)行一系列的擴展,并提供相應(yīng)的參考實現(xiàn),用戶只需要在擴展的基礎(chǔ)上增加自己的業(yè)務(wù)邏輯,便可以快捷地創(chuàng)建功能更為復(fù)雜的 Eclipse 向?qū)А?/p>

如不做特殊說明,本文默認(rèn)的開發(fā)和運行環(huán)境是:IBM JDK 1.6,Eclipse 3.4.x

Eclipse 向?qū)C制介紹

在 Eclipse 中,向?qū)且环N很好的輔助用戶操作的機制,通常用于指導(dǎo)用戶完成特定的業(yè)務(wù)操作,例如:創(chuàng)建一個 java 工程,導(dǎo)入一個文件,導(dǎo)出一個 JAR 文件等等,在 Eclipse 中都有相應(yīng)的向?qū)лo助用戶完成。此外,在 Eclipse 插件開發(fā)中,向?qū)б灿玫梅浅F毡椋珽clipse 提供的向?qū)Э蚣芸梢詭椭脩艨焖賱?chuàng)建自己的向?qū)А?/p>

向?qū)Щ静僮骱瓦\行機制

開始之前,我們先來了解一下 Eclipse 向?qū)У膶崿F(xiàn)機制。只有對 Eclipse 向?qū)У膶崿F(xiàn)機制有深入了解,才能實現(xiàn)合理的擴展。 Eclipse 向?qū)в梢幌盗械南驅(qū)ы摻M成,通常用戶的操作會被分散到各個向?qū)ы摚總€向?qū)ы撚糜谂渲貌僮魉璧哪骋环矫娴男畔ⅲ?dāng)所有向?qū)ы摰呐渲猛瓿芍螅麄€向?qū)П憧梢詧?zhí)行最后的操作并結(jié)束。此外,在向?qū)гO(shè)計中,用戶需要將當(dāng)前向?qū)ы撍斜匦栊畔⑻詈茫癗ext”按鈕才生效,從而進(jìn)入下一個向?qū)ы摗.?dāng)所有向?qū)ы摰膬?nèi)容填充完畢并且到達(dá)最后一個向?qū)ы摃r,向?qū)У摹癋inish”按鈕才能有效,這時候點擊“Finish”按鈕開始執(zhí)行向?qū)У哪繕?biāo)操作。

以 Eclipse 中創(chuàng)建一個工程的向?qū)槔蜷_ Eclipse 開發(fā)環(huán)境,選擇“File->New->PRoject”,便會彈出一個創(chuàng)建新工程的向?qū)В鐖D 1 所示。可以看到,該向?qū)е杏袃蓚€頁面,第一個頁面用于選擇需要創(chuàng)建的工程類型,我們選擇“General”中的“Project”創(chuàng)建一個 Eclipse 普通工程,第二個頁面用于配置創(chuàng)建 Eclipse 普通工程所需要的信息:包括工程名,工程位置以及工程所屬的工作集。只有在第一頁中選好需要創(chuàng)建的工程類型之后,“Next”按鈕才有效,進(jìn)而進(jìn)入第二頁,當(dāng)?shù)诙撝兴斜靥钚畔⑻钔曛螅癋inish”按鈕才有效,點擊它將開始創(chuàng)建一個 Eclipse 工程的操作。

圖 1. Eclipse 中創(chuàng)建普通工程向?qū)?/h5>圖片示例

在 Eclipse 中,向?qū)П仨殞崿F(xiàn)接口 org.eclipse.jface.wizard.IWizard,Eclipse 提供的 org.eclipse.jface.wizard.Wizard 是 IWizard 的一個抽象實現(xiàn)。向?qū)ы摫仨殞崿F(xiàn)接口 org.eclipse.jface.wizard.IWizardPage,org.eclipse.jface.wizard.WizardPage 是 IWizardPage 的一個抽象實現(xiàn)。用戶如果想使用 Eclipse 提供的框架創(chuàng)建自己的向?qū)В敲聪驅(qū)Ш拖驅(qū)ы撔枰謩e繼承 Wizard 類和 WizardPage 類并重寫相應(yīng)方法。 創(chuàng)建一個 Eclipse 向?qū)Ш笈_發(fā)生的操作順序大致如下,在這個過程中,我們需要重寫第一步中向?qū)У臉?gòu)造函數(shù),以及第三步中添加向?qū)ы摬僮鳌?nbsp;1. 使用 IWizard 子類的構(gòu)造函數(shù)創(chuàng)建 Eclipse 向?qū)В?nbsp;2. 創(chuàng)建向?qū)诘?Shell; 3. 添加向?qū)ы摚篴ddPages(),重寫該方法給向?qū)Р迦氲南驅(qū)ы摚?nbsp;4. 創(chuàng)建向?qū)ы撊萜鳎篧izardDialog.createPageContainer(Composite parent); 5. 創(chuàng)建每個向?qū)ы搶?yīng)的 Control:IWizard.createPageControls(Composite pageContainer)。Eclipse 調(diào)用它來實例化所有的向?qū)ы撁妗V貙懰o向?qū)砑映掷m(xù)可視的窗體小部件; 6. 顯示起始向?qū)ы摚赫{(diào)用 WizardDialog.showStartingPage():重寫該方法以獲取向?qū)У谝粋€頁面。

向?qū)ы摱ㄖ?/h3>

下面我們來看一下向?qū)ы摰亩ㄖ疲驅(qū)ы摂U展了 WizardPage 類。開發(fā)人員為了定制自己的頁面,必須重寫下面一些方法:

Constructor:實例化向?qū)ы撁妗ispose():向?qū)шP(guān)閉時調(diào)用該方法清除向?qū)ы撓嚓P(guān)對象。createControl(Composite parent):重寫它來創(chuàng)建向?qū)ы摽丶Wizard getWizard():獲取向?qū)ы撍诘南驅(qū)ο蟆etPageComplete:當(dāng)該向?qū)ы撝械乃斜仨毜脑O(shè)置都完成之后,可以將該頁的狀態(tài)設(shè)置為結(jié)束,然后用戶可以進(jìn)入下一頁。setTitle(String title):設(shè)置向?qū)ы摌?biāo)題。setDescription(String description):設(shè)置向?qū)ы摰拿枋觥etImageDescriptor(ImageDescriptor image):提供頁面右上方出現(xiàn)的圖片。setMessage(String message):設(shè)置向?qū)ы撝械奶崾拘畔ⅰetErrorMessage(String error): 設(shè)置向?qū)ы撝械腻e誤提示信息。performHelp():設(shè)置向?qū)ы摰膸椭畔ⅰ?p style="margin-top:0px; margin-bottom:0px; padding-top:6px; padding-bottom:6px; border:0px; outline:0px; vertical-align:baseline; color:rgb(34,34,34); line-height:1.5em; font-size:1.166em!important">當(dāng)向?qū)е杏卸鄠€向?qū)ы摃r,我們可以在向?qū)υ捒蜃钕路娇吹健癇ack”,“Next”,“Finish”和“Cancel”四個按鈕。“Back”,“Next”按鈕用于在多個向?qū)ы撻g進(jìn)行跳轉(zhuǎn),當(dāng)向?qū)е兄挥幸粋€向?qū)ы摃r,只有“Finish”和“Cancel”兩個按鈕。

“Back”按鈕:用于返回到前一個向?qū)ы摗|c擊該按鈕,將調(diào)用函數(shù) IWizardPage getPreviousPage(IWizardPage previousPage),返回前一個頁面。“Next”按鈕:用于進(jìn)入下一個向?qū)ы摗τ谝粋€設(shè)計合理的向?qū)В挥挟?dāng)前向?qū)ы撝兴斜靥畹男畔⒃O(shè)置完成之后,“Next”按鈕才能變成有效狀態(tài),然后用戶才被允許進(jìn)入下一個頁面。當(dāng)用戶填完頁面中的必須信息時,程序?qū)?zhí)行 setPageComplete(true) 方法將當(dāng)前向?qū)ы摖顟B(tài)設(shè)為完成狀態(tài);之后用戶點擊“Next”按鈕,向?qū)ы?IWizardPage 的方法 getNextPage(IWizardPage nextPage) 被調(diào)用,返回下一個向?qū)ы摗DJ(rèn)情況下,用戶將進(jìn)入向?qū)ь?Wizard 的 addPages() 方法所提供的數(shù)組中的下一個頁面。如果我們要實現(xiàn)下一頁有多種方案,必須重寫該方法來計算后一個頁面。“Finish”按鈕:當(dāng)所有向?qū)ы撝械男畔⒁呀?jīng)配好之后,用戶點擊 Finish 按鈕,調(diào)用 performFinish() 函數(shù)來執(zhí)行向?qū)繕?biāo)操作,用戶需要重寫它來實現(xiàn)向?qū)У臉I(yè)務(wù)邏輯,如果 performFinish() 執(zhí)行業(yè)務(wù)邏輯失敗,則應(yīng)該返回 false。“Cancel”按鈕:在向?qū)н\行過程中,用戶可以隨時點擊該按鈕,退出向?qū)А|c擊該按鈕,將會調(diào)用 performCancel() 函數(shù),取消當(dāng)前向?qū)Р僮鳎⒅八龅牟僮骰貪L。

Eclipse 向?qū)U展

從對 Eclipse 向?qū)C制分析可知,Eclipse 向?qū)ы摰奶砑邮蔷€性的,向?qū)ы摰膬?nèi)容也是固定的,頁面內(nèi)容和順序一旦確定就無法改變。在實際應(yīng)用中,我們面對的需求往往是復(fù)雜的,用戶的操作步驟經(jīng)常是有分支的,向?qū)ы摰膬?nèi)容有時候根據(jù)用戶的操作需要動態(tài)變化。下面我們從兩個方面對當(dāng)前 Eclipse 向?qū)C制進(jìn)行擴展:動態(tài)頁數(shù)的 Eclipse 向?qū)б约皹錉钔負(fù)浣Y(jié)構(gòu)的 Eclipse 向?qū)А?/p>

動態(tài)頁數(shù)的 Eclipse 向?qū)?/h3>

實際中,我們經(jīng)常遇到的一類問題是:某個向?qū)ы摰拇嬖谂c否依賴于用戶在前面向?qū)ы撝兴龅倪x擇。

舉個例子:我們需要給某電影院實現(xiàn)一個電影票購票系統(tǒng),觀眾能夠通過該系統(tǒng)遠(yuǎn)程連接到電影院的服務(wù)器進(jìn)行訂票,訂購電影票的用戶有三種類型:普通用戶,會員用戶,以及 VIP 會員,不同的用戶其訂票流程是不同的。根據(jù)需求,我們使用 Eclipse 的 RCP 來實現(xiàn)該電影票購票系統(tǒng),觀眾訂票操作將通過 Eclipse 向?qū)лo助完成,我們設(shè)計了四個向?qū)ы摚篈、B、C、D。向?qū)ы?A 供用戶選擇其用戶類型:普通用戶,普通會員或者 VIP 會員。假如觀眾是普通用戶則直接進(jìn)入向?qū)ы?B 填寫其基本信息,包括姓名,電話號碼等等,之后進(jìn)入向?qū)ы?C 選擇電影票,包括電影名字,時間,座位號等,然后選擇確定,操作結(jié)束。假如觀眾是會員或者 VIP 會員時,觀眾在向?qū)ы?A 輸入自己的會員 ID 和密碼登錄到系統(tǒng),登錄成功之后,直接進(jìn)入向?qū)ы?C 選擇電影票,操作和普通用戶一樣,當(dāng)電影票選票結(jié)束之后,會員還將進(jìn)入向?qū)ы?D,查看其歷史記錄,剩余余額等信息。四個向?qū)ы摰木唧w描述如下:

表 1. 電影訂票向?qū)гO(shè)計
向?qū)ы摼幪?/th>標(biāo)題內(nèi)容
A用戶類型選擇選擇用戶類型:普通用戶,普通會員,VIP 會員。如果是會員用戶,需要輸入自己的會員 ID 和密碼進(jìn)行登錄
B普通用戶基本信息對于普通用戶,填寫其基本信息,包括用戶名,電話號碼
C電影票信息用戶選擇其想看的電影,選擇電影名字,放映時間,以及選擇座位號
D歷史記錄對于會員用戶,操作結(jié)束之后,將顯示其歷史紀(jì)錄

向?qū)ы擁樞驁D如下,向?qū)ы撌莿討B(tài)變化的。當(dāng)用戶為普通用戶與,向?qū)ы?B 出現(xiàn),D 不出現(xiàn),當(dāng)用戶為會員用戶,向?qū)ы?B 不出現(xiàn),D 出現(xiàn)。

圖 2. 電影訂票動態(tài)向?qū)ы樞驁D
圖片示例

對于普通用戶:在向?qū)ы?A 中選擇普通用戶類型,然后進(jìn)入向?qū)ы?B,填寫其基本信息,然后進(jìn)入向?qū)ы?C 進(jìn)行選票并結(jié)束。 見下圖。

圖 3. 普通用戶電影訂票流程
圖片示例

對于會員或者 VIP 會員用戶:在向?qū)ы?A 中選擇會員用戶或者 VIP 會員,跳過向?qū)ы?B,直接進(jìn)入向?qū)ы?C,選票結(jié)束之后,進(jìn)入向?qū)ы?D,查看其歷史紀(jì)錄。見下圖。

圖 4. 會員用戶以及 VIP 會員用戶電影訂票流程
圖片示例

為了實現(xiàn)向?qū)ы摰膭討B(tài)增加或者減少功能,本文提供了一個動態(tài)向?qū)У某橄箢?DynamicPageWizard,供廣大開發(fā)人員使用。用戶使用時,只需要繼承該抽象類,并重寫向?qū)ы摮跏蓟黾樱薷模约皠h除等方法,便可以方便地實現(xiàn)動態(tài)向?qū)АT撓驅(qū)ь惱^承了類 org.eclipse.jface.wizard.Wizard,在原 Wizard 的基礎(chǔ)上進(jìn)行擴展,使用變量 List<IWizardPage> pages 來存儲向?qū)е械乃邢驅(qū)ы摚愔兴袑ο驅(qū)ы摰牟僮鞫际腔谠撟兞窟M(jìn)行,包括向?qū)ы摰膭?chuàng)建、注銷、動態(tài)增加以及刪除。詳細(xì)的內(nèi)容見下面清單。由于使用 pages 變量覆蓋了原 org.eclipse.jface.wizard.Wizard 中的 pages 變量,因而父類方法中基于該變量的所有方法都需要重寫,在下表中省略號部分是重寫的代碼,讀者可以根據(jù)自己的 JDK 版本以及擴展需要,將內(nèi)容補上。

清單 1. 動態(tài)頁數(shù)向?qū)Ц割?DynamicPageWizard
 public abstract class DynamicPageWizard extends Wizard {     /**      * 向?qū)е械乃邢驅(qū)ы摚⒁猓褐傅氖窃黾踊蛘邷p少之后的向?qū)ы?    */     private List<IWizardPage> pages = new ArrayList<IWizardPage>();     ...         /**      * 構(gòu)造函數(shù),創(chuàng)建一個空的向?qū)?    */     protected DynamicPageWizard() {         super();     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#addPage(org.eclipse.jface.wizard.IWizardPage)      */     public void addPage(IWizardPage page) {     	 // 重寫父類方法,添加向?qū)ы摚⑾驅(qū)ы摰南驅(qū)гO(shè)置為當(dāng)前對象    	 ...     }         /**      * 在指定的向?qū)ы撉安迦胂驅(qū)ы?    *      * @param page      * @param nextPage      * @return      */     public boolean addPage(IWizardPage page, IWizardPage nextPage) {     	 for(int i = 0; i < pages.size(); i++) {     		 if(pages.get(i) == nextPage) {     			 return addPage(page, i);     		 }     	 }     	 return false;     }         /**      * 在指定的位置插入向?qū)ы?    *      * @param page      * @param location      */     public boolean addPage(IWizardPage page, int location) {     	 // Invalid location     	 if(location < 0 || location > pages.size())     		 return false;     	    	 // Create the new page list     	 List<IWizardPage> newPages = new ArrayList<IWizardPage>();     	 for(int i = 0; i < location; i++) {     		 newPages.add(pages.get(i));     	 }     	    	 page.setWizard(this);     	 newPages.add(page);     	    	 for(int i = location; i < pages.size(); i++) {     		 newPages.add(pages.get(i));     	 }     	    	 // Set the relationship     	 if(location != pages.size())     		 ((IWizardPage)newPages.get(location + 1)).setPreviousPage(page);     	    	 ((IWizardPage)page).setPreviousPage((IWizardPage)newPages.get(location - 1));     	 pages = newPages;     	 return true;     }         /**      * 刪除指定位置的向?qū)ы?    *      * @param number      */     public void removePage(int number) {     	 if(number < 0)     		 return;     	 if(number > pages.size() - 1)     		 return;     	 if(number == 0)     		 pages.remove(0);     	 else if(number == pages.size() - 1)     		 pages.remove(number);     	 else { 	    	 IWizardPage wizarPage = (IWizardPage)pages.get(number + 1); 	   		 wizarPage.setPreviousPage((IWizardPage)pages.get(number - 1)); 	   		 pages.remove(number);     	 }     }         /**      * 刪除指定的向?qū)ы?    *      * @param page      */     public void removePage(IWizardPage page) {     	 int number = -1;     	 for(int i = 0; i < pages.size(); i++) {     		 if(pages.get(i) == page)     			 number = i;     	 }     	    	 removePage(number);     }             /**      * 刪除向?qū)е心撤N類名的所有向?qū)ы?    *      * @param number      */     public void removePage(String className) {        for(int i = 0; i < pages.size(); i++) {     	 if(pages.get(i).getClass().getCanonicalName().equalsIgnoreCase(className))     			 removePage(i);     	 }     }     	 /* 	 * (non-Javadoc) 	 * @see org.eclipse.jface.wizard.Wizard#addPages() 	 */     public void addPages() {     	 // 重寫父類方法    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#canFinish()      */     public boolean canFinish() {     	 // 重寫父類方法,檢測是否所有向?qū)ы摰脑O(shè)置都結(jié)束    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#createPageControls      * (org.eclipse.swt.widgets.Composite)      */     public void createPageControls(Composite pageContainer) {     	 // 重寫父類方法    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#dispose()      */     public void dispose() {     	 // 重寫父類方法    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getDefaultPageImage()      */     public Image getDefaultPageImage() {     	 // 重寫父類方法    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getNextPage      * (org.eclipse.jface.wizard.IWizardPage)      */     public IWizardPage getNextPage(IWizardPage page) {     	 // 重寫父類方法,獲取下一個向?qū)ы?   	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getPage(java.lang.String)      */     public IWizardPage getPage(String name) {     	 // 重寫父類方法,獲取指定名字的向?qū)ы?   	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getPageCount()      */     public int getPageCount() {     	 // 重寫父類方法    }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getPages()      */     public IWizardPage[] getPages() {     	 // 重寫父類方法    }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getPreviousPage      * (org.eclipse.jface.wizard.IWizardPage)      */     public IWizardPage getPreviousPage(IWizardPage page) {     	 // 重寫父類方法,獲取某個向?qū)ы撝暗南驅(qū)ы?   }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getStartingPage()      */     public IWizardPage getStartingPage() {     	 // 重寫父類方法,獲取起始向?qū)ы?   }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#performCancel()      */     public boolean performCancel() {     	 // 重寫父類方法    }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#needsPreviousAndNextButtons()      */     public boolean needsPreviousAndNextButtons() {     	 // 重寫父類方法    }         /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#setForcePreviousAndNextButtons(boolean)      */     public void setForcePreviousAndNextButtons(boolean b) {     	 // 重寫父類方法    }         /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#performFinish()      */     public abstract boolean performFinish();     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#setDefaultPageImageDescriptor      * (org.eclipse.jface.resource.ImageDescriptor)      */     public void setDefaultPageImageDescriptor(ImageDescriptor imageDescriptor) {     	 // 重寫父類方法    }  }

樹狀拓?fù)浣Y(jié)構(gòu)的 Eclipse 向?qū)?/h3>

繼續(xù)以電影票購票系統(tǒng)為例說明,現(xiàn)在用戶對該系統(tǒng)提出了新的需求,要求除了預(yù)定電影票之外,訂票者還能通過該系統(tǒng)申請成為會員,以及普通會員申請成為 VIP 會員。這樣用戶的操作出現(xiàn)了分支,我們需要在前面實現(xiàn)的向?qū)ЩA(chǔ)上增加新的一個向?qū)ы摚怨┯脩暨x擇操作類型:電影票預(yù)訂,申請成為會員或者升級為 VIP 會員。假如用戶選擇“電影票預(yù)訂”,便進(jìn)入上一節(jié)中實現(xiàn)的訂票界面。假如用戶選擇“申請成為會員”或者“升級為 VIP 會員”,便分別進(jìn)入另兩條分支,進(jìn)行相應(yīng)操作。

根據(jù)上面分析,我們需要實現(xiàn)如下向?qū)ы摗?/p>

向?qū)ы摼幪?/th>標(biāo)題內(nèi)容
A操作類型選擇選擇用戶操作類型:電影票預(yù)訂,申請成為會員或者升級為 VIP 會員
B用戶類型選擇選擇用戶類型:普通用戶,普通會員,VIP 會員
C申請成為會員普通用戶申請成為會員操作
D升級為 VIP 會員普通會員升級成為 VIP 會員操作
E普通用戶基本信息對于普通用戶,填寫其基本信息,包括用戶名,電話號碼
F電影票信息用戶選擇其想看的電影,選擇電影名字,放映時間,以及選擇座位號
G歷史記錄對于會員用戶,操作結(jié)束之后,將顯示其歷史紀(jì)錄

該向?qū)У臉湫屯負(fù)浣Y(jié)構(gòu)如下。需要特別指出的是,電影票預(yù)訂操作,也就是第二級節(jié)點向?qū)ы?B 處的實現(xiàn)方式和前面是完全不同的,這里使用的是數(shù)狀的拓?fù)浣Y(jié)構(gòu),而前面采用的是頁面動態(tài)增加或者減少方式。

圖 5. 電影訂票樹狀拓?fù)浣Y(jié)構(gòu)
圖片示例

首先在向?qū)ы?A 中選擇操作類型,如果是電影票預(yù)訂操作,則進(jìn)入向?qū)ы?B,如果是申請成為會員,則進(jìn)入向?qū)ы?C,如果是升級為 VIP 會員,則進(jìn)入向?qū)ы?D,這是第一次分支;當(dāng)用戶選擇電影票預(yù)訂并進(jìn)入向?qū)ы?B 之后,用戶再選擇其用戶類型,這是該向?qū)У牡诙畏种В绻脩羰瞧胀ㄓ脩簦瑒t進(jìn)入向?qū)ы?E 填寫普通用戶基本信息,然后進(jìn)入向?qū)ы?F 進(jìn)行選票并結(jié)束;如果用戶是會員或者 VIP 會員,則直接進(jìn)入向?qū)ы?F,選票結(jié)束之后,進(jìn)入向?qū)ы?G,查看其歷史紀(jì)錄。

普通用戶預(yù)定電影票操作:首先在向?qū)ы?A 中,選擇電影票預(yù)訂,進(jìn)入訂票分支;然后在向?qū)ы?B 中,選擇普通用戶,進(jìn)入普通用戶訂票分支。見下圖。

圖 6. 普通用戶電影訂票流程
圖片示例

會員用戶預(yù)定電影票操作:首先在向?qū)ы?A 中,選擇電影票預(yù)訂,進(jìn)入訂票分支;然后在向?qū)ы?B 中,選擇會員用戶,輸入會員用戶名和密碼,進(jìn)入會員用戶訂票分支。見下圖。

圖 7. 會員用戶電影訂票流程
圖片示例

申請成為會員操作:在向?qū)ы?A 中,選擇申請成為會員,進(jìn)入申請成為會員分支。見下圖。

圖 8. 申請成為會員流程
圖片示例

為了實現(xiàn)樹狀拓?fù)浣Y(jié)構(gòu),文章提供了一個樹狀向?qū)У某橄箢?TreePageWizard,以及向?qū)ы擃?TreeWizardPage 供開發(fā)人員使用。用戶使用時,只需要將其向?qū)ь惱^承 TreePageWizard,向?qū)ы擃惱^承 TreeWizardPage,重寫這兩個類中相應(yīng)的方法,便可以方便地實現(xiàn)樹狀拓?fù)浣Y(jié)構(gòu)向?qū)А?/p>

向?qū)ь?TreePageWizard 繼承自類 org.eclipse.jface.wizard.Wizard,在原 Wizard 的基礎(chǔ)上進(jìn)行擴展,使用變量 TreeWizardPage rootPage 來存儲樹結(jié)構(gòu)的根節(jié)點對應(yīng)的向?qū)ы摚瑯浣Y(jié)構(gòu)的根節(jié)點即是該向?qū)У钠鹗柬摗J褂米兞?Set<TreeWizardPage> pages 來存儲樹結(jié)構(gòu)中的所有向?qū)ы摗n愔兴胁僮鞫际菄@這兩個變量進(jìn)行,包括樹結(jié)構(gòu)中節(jié)點的添加、刪除、樹結(jié)構(gòu)分支的選擇等等。和動態(tài)向?qū)Р煌氖牵琾ages 里面保存的向?qū)ы撌窍驅(qū)е兴锌赡艿捻撁妫?DynamicPageWizard 中存儲的是當(dāng)前向?qū)е械捻撁妫⑶?pages 的類型是 Set<TreeWizardPage>,DynamicPageWizard 中類型是 List<IWizardPage>,詳細(xì)的內(nèi)容見下面清單。同樣,由于 pages 變量覆蓋了原 org.eclipse.jface.wizard.Wizard 中的 pages 變量,之前基于該變量的所有方法都需要重寫,讀者可以根據(jù)不同的 JDK 版本以及自己的需要,將必須重寫部分內(nèi)容補上。

清單 2. 樹狀拓?fù)湎驅(qū)Ц割?TreePageWizard
 public abstract class TreePageWizard extends Wizard {     /**      * 樹型向?qū)У钠鹗柬?    * Root page.      */     private TreeWizardPage rootPage = null;         /**      * 向?qū)е械乃邢驅(qū)ы?    * All the pages in the wizard.      */     private Set <TreeWizardPage> pages = new HashSet <TreeWizardPage>();     /**      * 構(gòu)造函數(shù)     * Creates a new empty wizard.      */     protected TreePageWizard () {         super();     }     /**      * 構(gòu)造函數(shù)     * Creates a new empty wizard.      */     protected TreePageWizard (IWizardPage page) {         super();     	 if(page instanceof TreeWizardPage) {     		 rootPage = (TreeWizardPage)page;     		 addPage(rootPage);     	 }     }         /**      * 設(shè)置樹結(jié)構(gòu)的根節(jié)點,以及向?qū)У钠鹗柬?    */     public void setRootPage(IWizardPage page) {     	 if(page instanceof TreeWizardPage) {     		 addPage((TreeWizardPage)page);     		 rootPage = (TreeWizardPage)page;     	 }     }         /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#addPage(org.eclipse.jface.wizard.IWizardPage)      */     public void addPage(IWizardPage page) {     	 // 判斷是否 TreeWizardPage 類型的向?qū)В绻皇牵瑒t返回    	 if(!(page instanceof TreeWizardPage))     		 return;     	    	 // 添加該向?qū)ы?   	 pages.add((TreeWizardPage)page);     	 page.setWizard(this);     	    	 // 添加該向?qū)ы摰乃凶酉驅(qū)ы?   	 List <TreeWizardPage> children = ((TreeWizardPage)page).getChildren();     	 for(int i = 0; i  < children.size(); i++) {     		 addPage(children.get(i));     	 }     }         /**      * 插入向?qū)ы摚谝粋€參數(shù)為待插入的向?qū)ы摚诙€參數(shù)為插入位置之前的向?qū)ы?    *      * @param page      * @param prviousPage      * @return      */     public void addPage(TreeWizardPage page, TreeWizardPage previousPage) {     	 boolean exist = pages.contains(previousPage);     	 if(!exist)     		 return;     	    	 if (previousPage.getChildren().add(page))     		 addPage(page);     }         /**      * 從向?qū)е袆h除向?qū)ы?    *      * @param page      * @return      */     public void removePage(TreeWizardPage page) {     	 pages.remove(page);     	 List <TreeWizardPage> children = page.getChildren();     	 for(int i = 0; i  < children.size(); i++) {     		 removePage(children.get(i));     	 }     }         /**      * 從向?qū)е袆h除向?qū)ы摚谝粋€參數(shù)為待刪除的向?qū)ы摚诙€參數(shù)為刪除位置之前的向?qū)ы?    *      * @param page      * @param prviousPage      * @return      */     public void removePage(TreeWizardPage page, TreeWizardPage previousPage) {     	 boolean exist = pages.contains(previousPage);     	 if(exist) { 	    	 if (previousPage.getChildren().remove(page)) 	    		 removePage(page);     	 }     }         /**      * 從向?qū)е袆h除向?qū)ы摚谝粋€參數(shù)為待刪除的向?qū)ы摰念惷诙€參數(shù)為刪除位置之前的向?qū)ы?    *      * @param className      * @param previousPage      * @return      */     public boolean removePage(String className, TreeWizardPage previousPage) {     	 boolean exist = pages.contains(previousPage);     	 if(!exist)     		 return false;     	    	 List <TreeWizardPage> children = previousPage.getChildren();     	 for(int i = 0; i  < children.size(); i++) {     		 TreeWizardPage temp = children.get(i);     		 if(temp.getClass().getCanonicalName().equalsIgnoreCase(className)) {     			 if (children.remove(temp)) {     				 removePage(temp);     	    		 return true;     	    	 } else     	    		 return false;     		 }     	 }     	    	 return false;     }     	 /* 	 * (non-Javadoc) 	 * @see org.eclipse.jface.wizard.Wizard#addPages() 	 */     public void addPages() {     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#canFinish()      */     public boolean canFinish() {     	 // 檢測是否所有向?qū)ы摰脑O(shè)置都完成,整個向?qū)Э梢越Y(jié)束    	 TreeWizardPage page = rootPage;     	 while (page != null) {     		 if(!page.isPageComplete())     			 return false;     		 page = page.getNextPage();     	 }         return true;     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#createPageControls      * (org.eclipse.swt.widgets.Composite)      */     public void createPageControls(Composite pageContainer) {     	 // 重寫父類方法    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#dispose()      */     public void dispose() {     	 // 重寫父類方法    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getDefaultPageImage()      */     public Image getDefaultPageImage() {     	 // 重寫父類方法    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getPreviousPage      * (org.eclipse.jface.wizard.IWizardPage)      */     public IWizardPage getPreviousPage(IWizardPage page) {     	 // 獲取特定向?qū)ы撝暗捻撁?       if(page == null)         	 return null;                 if(!(page instanceof TreeWizardPage))         	 return null;         return ((TreeWizardPage)page).getPreviousPage();     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getNextPage      * (org.eclipse.jface.wizard.IWizardPage)      */     public IWizardPage getNextPage(IWizardPage page) {     	 // 獲取特定向?qū)ы撝蟮捻撁?   	 if(page == null)     		 return null;     	    	 if(!(page instanceof TreeWizardPage))     		 return null;     	    	 return page.getNextPage();     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getPage(java.lang.String)      */     public IWizardPage getPage(String name) {     	 // 根據(jù)名字,獲取特定向?qū)ы?   	 Iterator <TreeWizardPage> iter = pages.iterator();     	 while(iter.hasNext()) {             IWizardPage page = (IWizardPage) iter.next();             String pageName = page.getName();             if (pageName.equals(name)) { 				 return page; 			 }         }         return null;     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getPageCount()      */     public int getPageCount() {     	 // 重寫父類方法,獲取該樹型結(jié)構(gòu)向?qū)е兴械南驅(qū)ы摰臄?shù)目    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getPages()      */     public IWizardPage[] getPages() {     	 // 重寫父類方法,獲取該樹型結(jié)構(gòu)向?qū)е兴械南驅(qū)ы?   	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#getStartingPage()      */     public IWizardPage getStartingPage() {     	 // 重寫父類方法,獲取起始向?qū)ы?   	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#performCancel()      */     public boolean performCancel() {     	 // 重寫父類方法    	 ...     }     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#needsPreviousAndNextButtons()      */     public boolean needsPreviousAndNextButtons() {     	 // 重寫父類方法    	 ...     }         /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#setForcePreviousAndNextButtons(boolean)      */     public void setForcePreviousAndNextButtons(boolean b) {     	 // 重寫父類方法    	 ...     }         /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#performFinish()      */     public abstract boolean performFinish();     /*      * (non-Javadoc)      * @see org.eclipse.jface.wizard.Wizard#setDefaultPageImageDescriptor      * (org.eclipse.jface.resource.ImageDescriptor)      */     public void setDefaultPageImageDescriptor(ImageDescriptor imageDescriptor) {         // 重寫父類方法        ...     }  }

我們再來看一下向?qū)ы擃?TreeWizardPage 的實現(xiàn),該類繼承了類 org.eclipse.jface.wizard.WizardPage,樹狀向?qū)е兴械南驅(qū)ы摱急仨毨^承此類,使用變量 List <TreeWizardPage> children 存儲該樹節(jié)點所有的孩子節(jié)點,使用變量 TreeWizardPage nextPage 存儲當(dāng)前向?qū)ы搶⒁D(zhuǎn)到的下一向?qū)ы摚琻extPage 必須是 children 中的某一個向?qū)ы摗reeWizardPage 類中其他方法實現(xiàn)了對該向?qū)ы撍泻⒆庸?jié)點的增加、刪除、獲取等操作,以及設(shè)置下一向?qū)ы摰炔僮鳎暾麅?nèi)容見下面清單。

清單 3. 樹狀拓?fù)湎驅(qū)ы摳割?TreeWizardPage
public class TreeWizardPage extends WizardPage {    /**    * 當(dāng)前向?qū)ы撍锌赡艿南乱粋€向?qū)ы?  */    private List <TreeWizardPage> children = new ArrayList <TreeWizardPage>();    /**    * 當(dāng)前向?qū)У南乱粋€向?qū)ы?  */    private TreeWizardPage nextPage = null;    /**    * 構(gòu)造函數(shù)   *    * @param pageName    */    protected TreeWizardPage(String pageName) {      super(pageName);    }    /**    * 構(gòu)造函數(shù)   *    * @param pageName    * @param title    * @param titleImage    */    protected TreeWizardPage(String pageName, String title,          ImageDescriptor titleImage) {      super(pageName, title, titleImage);    }    /*    * (non-Javadoc)    *    * @see    * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets    * .Composite)    */    public void createControl(Composite parent) {    }    /*    * (non-Javadoc)    *    * @see org.eclipse.jface.wizard.WizardPage#getNextPage()    */    public TreeWizardPage getNextPage() {      return nextPage;    }    /**    * 設(shè)置該向?qū)У南乱豁?  *    * @param nextPage    *            the nextPage to set    */    public void setNextPage(TreeWizardPage nextPage) {      for (int i = 0; i  < children.size(); i++) {        if (children.get(i) == nextPage) {          this.nextPage = nextPage;          updateContainerButton();        }      }      this.nextPage = null;    }    /**    * 設(shè)置該向?qū)У南乱豁?  *    * @param className    */    public void setNextPage(String className) {     int number = -1;      for (int i = 0; i  < children.size(); i++) {        if (children.get(i).getClass().getCanonicalName().equalsIgnoreCase(className))          number = i;      }      if (number != -1) {        this.nextPage = children.get(number);        updateContainerButton();      } else        this.nextPage = null;    }    /**    * 添加可能的下一個向?qū)ы?  *    * @param page    */    public void addChild(TreeWizardPage page) {      if (page != null) {        children.add(page);        page.setPreviousPage(this);      }    }    /**    * 刪除可能的下一個向?qū)ы?  *    * @param page    */    public void removeChild(TreeWizardPage page) {      if (page != null) {        if (children.contains(page))          children.remove(page);      }    }    /**    * 獲取所有可能的下一個向?qū)ы?  *    * @return the children    */    public List <TreeWizardPage> getChildren() {      return children;    }    /**    * 更新向?qū)е械陌粹o,包括上一步按鈕,下一步按鈕,結(jié)束按鈕以及取消按鈕   */    public void updateContainerButton() {      getContainer().updateButtons();    }  }

關(guān)于上文中兩個例子的具體實現(xiàn),讀者可以在附件 EclipseWizardExtension.zip 中找到,考慮到不同 JDK 以及版權(quán)的問題,并沒有將兩種向?qū)У母割?DynamicPageWizard 和 TreePageWizard 放在附件中,讀者僅需要在 org.eclipse.expand.wizard 包中重建這兩個類,并把文中省略部分補全即可。

小結(jié)

本文對 Eclipse 向?qū)C制進(jìn)行了兩個方面的擴展,在原有 Eclipse 向?qū)У幕A(chǔ)上,擴展實現(xiàn)了一種動態(tài)頁數(shù)的向?qū)В约耙环N具有樹狀拓?fù)浣Y(jié)構(gòu)的向?qū)А討B(tài)頁數(shù)向?qū)еС衷谙驅(qū)е腥我馓砑踊蛘邉h除新的向?qū)ы摚瑢崿F(xiàn)時向?qū)ь愋枰^承 DynamicPageWizard 類,并重寫動態(tài)添加或者刪除向?qū)ы摲椒ǎ欢鴺錉钔負(fù)浣Y(jié)構(gòu)使得向?qū)Ц鶕?jù)用戶不同選擇,其流程可以實現(xiàn)分支,樹狀向?qū)枰^承 TreePageWizard 類,向?qū)ы撔枰^承 TreeWizardPage 類,并分別重寫父類中的相應(yīng)方法。基于這兩種擴展,用戶可以快速編寫復(fù)雜的 Eclipse 向?qū)崿F(xiàn),滿足實際需要。

聲明:本文僅代表作者個人觀點,不代表 IBM 公司之觀點。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

主站蜘蛛池模板: 新干县| 遵义市| 余干县| 庆元县| 绍兴市| 双峰县| 隆德县| 营山县| 平遥县| 肥东县| 东乡族自治县| 曲周县| 和平县| 红河县| 西乡县| 龙井市| 定陶县| 南通市| 思茅市| 张北县| 静海县| 长泰县| 唐海县| 怀宁县| 邓州市| 栾城县| 梅河口市| 清丰县| 宣汉县| 香港| 旬邑县| 邯郸县| 大姚县| 永福县| 驻马店市| 徐水县| 东宁县| 九龙坡区| 上杭县| 芜湖市| 乌拉特前旗|