歡迎您光臨本站 註冊首頁

GWT-Ext 體驗之旅,第 2 部分: 體驗 Panel 和 Window

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  

GWT-Ext 是基於 Google Web Toolkit(GWT)和 ExtJs 的功能強大的網頁開發控制項庫。它非常適用於進行純 Java 語言的富 Internet 應用的快速開發。本系列文章將詳細講解 GWT-Ext 的基本結構和功能特點,並通過代碼示例來演示該技術的具體實現。本文是該 系列 的第 2 部分,將介紹非常重要的控制項 Pannel,它是很多其它控制項的基礎容器。

Panel 是 GWT-Ext 中間非常重要的一個控制項。作為很多控制項的基礎容器,Panel 提供許多簡潔的方法,實現了諸如設置標題,設置圖標,設置支持拖拽等實用功能。並且以 Panel 基礎的擴展容器控制項,如 Tab Panel,Portal,Window,Progress Window 等,給 GWT-Ext 的使用者提供了極大的選擇餘地和靈活性。下面我們將從 Panel 開始介紹。

Panel

Panel 是一種容器,它提供了一組特定的功能和結構化組件,方便用戶進行應用程序圖形界面的組織。一個 Panel 可以包含頭,尾和內容體三部分,並可在其頭腳部分實現工具欄。 Panel 本身具備自動伸展的行為,並提供了一些工具按鈕來幫助用戶構建個性化的功能。

用戶可以通過以下的構造方法來初始化一個 Panel, 並指定其標題和內容。

Panel(java.lang.String title, java.lang.String html)

或者可通個空的構造方法來構建一個 Panel 對象,然後通過 Panel 的 setTitle 和 setHtml 方法來設置 Panel 的標題和其內容,

public void setTitle(java.lang.String title)    public void setHtml(java.lang.String html)

從 setHtml 方法名可以看出,Panel 將自動將傳入的內容作為 html 格式來解析,並進行展現。

Panel 提供了伸縮功能,該功能可將內容體進行隱藏,只將 Panel 的標題部分顯示,使用戶在不進行屏幕上下滑動的同時看到多個 Panel 的內容,並通過標題找到不同 Panel 里的內容。如圖 1 所示。


圖 1. Panel 的伸縮功能

用戶可以通過 Panel 對象的 setCollapsible 方法來設置 Panel 的伸縮特性。

public void setCollapsible(boolean collapsible) throws java.lang.IllegalStateException

當設置 collapsible 參數為 true 時,對應的 Panel 對象將具有可伸縮功能,此時在 Panel 的標題欄右則將會出現一個伸縮操作按鈕,用戶可以通過點擊該按鈕來決定將當前的 Panel 內容展現或隱藏。需要注意的是,該方法只有在 Panel 還沒有展現前調用,如當 Panel 展現后再調用該方法來設置伸縮性,將會得到 java.lang.IllegalStateException 異常。

在 Panel 的標題欄上除了 Panel 已有的伸縮功能按鈕外,用戶也可以添加一組個性化的按鈕,即工具欄。如圖 2 所示。


圖 2. 工具欄

設置 Panel 的工具欄,我們需要用到的方法是

public void setTools(Tool[] tools) throws java.lang.IllegalStateException    public void addTool(Tool tool) throws java.lang.IllegalStateException

從以上兩個方法可以看出,在初始化工具欄時,我們可以將所有工具一次性放入一個工具數組對象來完成,也可通過多次的逐個加入工具對象完成。與 setCollapsible 方法一樣,設置 panel 的工具欄也必需要在 panel 還沒有展現前完成。

setTools 和 addTool 方法中都用到了一個新的 Tool 類 , 我們可以通過 Tool 類的構造方法來初始化其實例對象。

public Tool(Tool.ToolType type, Function handler)

type 參數是 tool 在 panel 中展示的圖標類型,Tool 對象中已定義 19 種圖標供用戶選擇,如 Tool.GEAR, Tool.SEARCH 等,用戶可以根據自身功能的需要選擇最接近的圖標。除了圖標外,當用戶點擊圖標時,tool 對象應對相應功能進行響應,因此, 需要在 Function 參數中對相應 tool 對象的響應功能進行設置。

Function 本身是一個介面,當用戶點擊 tool 圖標時,介面中的 execute 方法將被調用,所以用戶可以通過定義一個匿名內部類並實現 Function 的唯一方法 void execute() 。如清單 1 所示。


清單 1. Function 實現方法
				New Function()    {       Public void execute()    {       MessageBox.alert( “ Settings ” , “ The Settings tool was clicked ” );    }    }

如該匿名內部類就是實現了 Function 介面,當用戶點擊相應的 tool 圖標時,屏幕中將出現一個消息框,如圖 3 所示。


圖 3. 消息框

Panel 的另外一個主要特性就是可以被設置為可拖拽的浮動框體。如圖 4 所示。


圖 4. Panel 的拖拽功能

實現 Panel 對象的拖拽功能可以通過 setDraggable 方法來完成

public void setDraggable(boolean draggable) throws java.lang.IllegalStateException

當 draggable 參數被設置為 true 時,該 panel 對象將具有拖拽的效果,該方法只有當 panel 被顯示前調用才有效。

在下載 GWTEXTDemo-all.zip中的 CommonPanels.java 中實現了上述所有功能。





Toolbar 和 Menus

工具欄能方便用戶進行相應功能操作,要得到一個 Toolbar 可以調用其構造方法

public Toolbar()

得到 Toolbar 對象后就可以在其中加入 tool 元素了,這些元素可以是工具欄按鈕,工具欄菜單按鈕或者工具欄分割符等。如圖 5 所示。


圖 5. Toolbar 對象

我們可以通過以下幾個方法分別加入 Toolbar 的不同類型的元素

public void addButton(ToolbarMenuButton button)    public void addButton(ToolbarButton button)    public void addSeparator()    public void addItem(ToolbarItem item)

ToolbarMenuButton 是一種 Toolbar 的菜單按鈕,點擊按鈕后將會彈出一個下拉菜單 ; ToolbarButton 是工具欄中的一個普通按鈕。為了工具欄的美觀,還可以在工具欄中加入分割符將工具欄中的各個元素進行隔離。除了按鈕和分割符之外,工具欄的中還可以加入工具欄項,如 ToolbarTextItem,它可以在工具欄中顯示為一個字元段。

對於 ToolbarButton 和 ToolbarTextItem 都只需要調用其對應的構造方法來生成實例

public ToolbarButton(java.lang.String text)    public ToolbarTextItem(java.lang.String text)

構造方法中的參數是工具欄按鈕的標題或工具欄字元域的內容。在獲得實例后,通過前面介紹的 Toobar 的方法將他們加入工具欄。

在工具欄中加入菜單按鈕的工作相對複雜。首先要實現一個 ToolbarMenuButton,它是按鈕類 Button 的一個子類,因此它具有按鈕類的所有特性。要生成一個 ToolbarMenuButton 的實例,可以通過構造方法

public ToolbarMenuButton(java.lang.String text,Menu menu)    public ToolbarMenuButton(java.lang.String text)

其中構造方法中的 text 參數是設置按鈕的標題,構造方法中的 menu 菜單參數用於設置用戶點擊該按鈕后彈出的菜單。如採用第二個構造方法,則要將實例化好的菜單對象通過 setMenu 方法設置進菜單按鈕。

Menu 對象即菜單,包含不同類型的項,每個項都可以包含子項。同一層次的項之間在菜單中將表現為上下關係。實現一個菜單對象可通過其構造方法

public Menu()

在獲得菜單實例后就是為其加入項。菜單中的項可以分為 Item, MenuItem, Separator,Adapter 幾類。其中 Item 類又可分為:

CheckItem,如圖 6 所示,


圖 6. CheckItem 項

ColorItem,如圖 7 所示


圖 7. ColorItem 項

DateItem,如圖 8 所示


圖 8. DateItem 項

可分別調用對應類的構造方法生成對像后,調用菜單對象的 addItem 方法將子項加入。

public void addItem(BaseItem item)

MenuItem 可用來創建菜單子項。首先通過 Menu 的構造方法創建子菜單對象,並通個 Menu 的 addItem 方法將各個項加入菜單子項,然後將整個子菜單對象通過 MenuItem 的構造方法中的 submenu 參數加入進父菜單中。

public MenuItem(java.lang.String text, Menu submenu)

其中 text 參數用來設置其在父菜單中的標題,submenu 參數即是已生成好的子菜單引用。 MenuItem 對象生成后,通過父菜單的 addItem 方法將其生成父菜單的項即可。

在下載 GWTEXTDemo-all.zip中的 ToolbarMenus.java 中實現了上述所有功能。





TabPanel

TabPanel 本身繼承自 Panel 類,因此 Panel 類的伸縮、工具欄、拖拽等特性對 TabPanel 類也適用。除此之外,TabPanel 還是一個 Tab 標籤的容器。如圖 9 所示。


圖 9. TabPanel

在增加 tab 標籤之前,我們需要一個 TabPanel 對象。以下是 TabPanel 的構造方法,

public TabPanel()

通過無參構造方法生成一個 TabPanel 實例后,需要對 TabPanel 實例的一些屬性進行設置,這些屬性將影響存在於其中的 tab 標籤的展現形式和一些行為,比如採用 setResizeTabs 設置 tab 標籤的寬度等。

public void setResizeTabs(boolean resizeTabs)

當 resizeTabs 參數為 true 時,每個 tab 標籤的寬度將會根據 TabPanel 容器的長度以及 tab 標籤的個數自動調節,從而使得所有 tab 頁正好充滿整個 TabPanel 容器。此時,如果在同一標籤容器里有很多 tab 標籤,則每個標籤能平均分到的寬度會非常小,導致標籤上的標題都有可能看不到。為了避免這種情況,通常在 setResizeTabs 被設置時,通過 setMinTabWidth 方法為標籤設置一個最小的寬度。

public void setMinTabWidth(int minTabWidth)

minTabWidth 參數是以像素為單位的一個整數。

當設置了最小寬度后,如果所有的 tab 標籤的寬度超過了容器 TabPanel 的寬度時,超出部分的 tab 標籤將不能看到,此時,通過 setEnableTabScroll 方法可使得 tab 標籤頁進行左右滾動,這樣被隱藏的 tab 標籤頁可以被看到

public void setEnableTabScroll(boolean enableTabScroll)    throws java.lang.IllegalStateException

通過該方法來設置 tab 標籤頁的左右滾動性,需要在 TabPanel 對象被顯示前設置,否則將導致 IllegalStateException 異常。

在 TabPanel 顯示時,可以通過 setActiveTab 方法設置默認顯示的 tab 標籤頁

public void setActiveTab(int activeTab)    public void setActiveTab(java.lang.String activeTab)

方法一通過 tab 頁的相對位置來確定顯示的 tab 頁,參數 activeTab 表示從左至右從零開始的一個序列數;方法二採用 tab 頁的唯一 id 來確定顯示的 tab 頁 ,參數 activeTab 表示要默認顯示的 tab 頁的 id 。

當 TabPanel 對象的一些基本屬性被設置好后,需要往其中加入 tab 標籤頁,每一個 TabPanel 中的 tab 標籤都是一個 Panel 對象 , TabPanel 對象作為 tab 標籤的容器 , 可以通過 add 方法將 panel 加入到 TabPanel 對象作為其一個 tab 標籤頁。

public void add(Component component)

TabPanel 處於顯示狀態后,可對每一個 tab 標籤操作所引起的事件進行監聽,這可通過調用 addListener 方法實現。

public void add(Component component)

TabPanel 處於顯示狀態后,可對每一個 tab 標籤操作所引起的事件進行監聽,這可通過調用 addListener 方法實現。

public void addListener(TabPanelListener listener)

將一個 TabPanelListener 的實例插入到 TabPanel 的監聽隊列中,TabPanelListener 是一個監聽介面,它支持以下幾種監聽方法

boolean doBeforeTabChange(TabPanel source, Panel newPanel, Panel oldPanel)    void onContextMenu(TabPanel source,Panel tab, EventObject e)    void onTabChange(TabPanel source,Panel tab)

從介面方法名可以看出,TabPanelListerner 可以捕捉到的 tab 標籤事件是:“標籤即將切換事件”,“標籤事件”和“標籤切換後事件”,用戶需要實現相應介面來處理的關心事件。 GWTExt 會將事件相關的對象注入到方法中,如 doBeforeTabChange 方法中的 source, newPanel 和 oldPanel 分別代表從原標籤對象 oldPanel 切換至新標籤對象 oldPanel 的引用,而 source 則代表標籤對象所在 TabPanel 的引用。

由於 TabPanelListener 是一個繼承於介面 PanelListener 的介面,直接對 TabPanelListener 進行實現將迫使用戶去實現定義在 PanelListener 中的眾多方法。即使可將方法體全部置空,但數以幾十的數量將使對 TabPanelListener 介面的實現變得枯燥而繁瑣。 GWTExt 在這個問題上充分為用戶考慮,設計了一個 TabPanelListenerAdapter 類,該類是對 TabPanelListener 介面及其父介面方法的一個實現類,但所有的方法體都是空。這樣用戶在定義 TabPanelLister 的實現時只需對相應方法進行覆蓋重寫即可,不必把所有介面方法全部實現。

在下載 GWTEXTDemo-all.zip中的 TabPanelDemo.java 中實現了上述所有功能。





Portal 和 Portlet

Portal 本身繼承自 Panel 類,它是一個 Portlet 容器。 Portal 可以添加 PortalColumn 或者 Portlet 作為子組件。 Portlet 模擬了網頁上可拖拽的 Portal 的效果。每個 Portlet 被分成數列,從上到下順序放置,每個 Portlet 都可拖拽至任意列的任意位置,如圖 10 所示。


圖 10. Portal

Portal,PortalColumn 和 Portlet 的關係如下 :

1. Portal 作為容器,可以包含任意個 PortalColumn 。以上圖為例,Portal 包含了三列。每一列都是一個 PortalColumn 的實例。

2. 每一個 PortalColumn 都可以包含任意個 Portlet,每個 Portlet 都可以拖拽到其它的 PortalColumn 中去。

用戶可以通過以下的構造方法來初始化一個 Portal 。

Portal()

我們提到 Portal 是一個容器,為了讓 Portal 和他包含的控制項之間上下左右出現間隔,Portal 繼承了 Panel 的 setPaddings 方法。

public void setPaddings(int padding) throws IllegalStateException

參數 padding 代表了間隔的像素值。如上圖所示,Portal 的藍框在上下左右四個方向和內部的 PortalColumn 留出了 15 個像素的空白,達到了美觀的效果。此外,Panel 也提供了 setPaddings 這個方法,可以單獨設定某幾個方向的空白。

public void setPaddings(int top, int left, int right, int bottom)    throws IllegalStateException

這個方法可以更靈活的控制界面的設計。此外,PortalColumn 和 Portlet 也繼承了 setPaddings 方法。

當實例化了一個 Portal 之後,我們需要給 Portal 分列。在我們的例子中,Portal 被分為了 3 列。因此我們需要創建三個 PortalColumn, PortalColumn 的構造函數如下所示。

PortalColumn()

為了指定 PortalColumn 在 Portal 容器中橫行所佔的比例,Portal 提供了一個 add() 的方法,如下所示。

public void add(Component component, LayoutData layoutData)

參數 component 代表了要加入 portal 的控制項,layoutData 代表了該控制項的布局屬性。在本例中,每個 PortalColumn 都佔用了 Portal 中 1/3 的空間,因此可以通過如下代碼來實現。

portal.add(firstColumn, new ColumnLayoutData(.33));

現在我們已經成功的創建了 Portal,並且將 PortalColumn 也加入到 Portal 中。接下來的工作就是創建可拖拽的 Portlet 。 Portlet 有三個構造函數。如下所示。

public Portlet()    public Portlet(String title, String html)    public Portlet(String title, String html, Tool[] tools)

Portlet 構造函數中的參數,如 title,html 和 tools 在前文已經提到且功能相同,這裡不在贅述。

Portlet 是繼承了 Panel 的控制項,因此它也是一個容器,它擁有容器的所有功能。比如可以設置布局管理器,可以添加其他 Panel, TreePanel 等控制項。

在下載 GWTEXTDemo-all.zip中的 PortalDemo.java 中實現了上述所有功能。





Window

在 GWT-Ext 中,Window 是繼承了 Panel 的控制項。它是一個浮動的並且可拖拽的窗口。常用的有如下五個構造函數。如下所示

Window()    Window(String title)    Window(String title, int width, int height)    Window(String title, boolean modal, boolean resizable)    Window(String title, int width, int height, boolean modal, boolean resizable)

參數 title 表示在 Window 上顯示的標題名;參數 width 表示初始化時的寬度,以像素為單位 ; 參數 height 表示初始化時的高度,以像素為單位;參數 modal 是一個布爾屬性,當它為 true 時,表示在初始化的時候這個 Window 出現在最前端,並且後面的所有組件不可選。如果為 false 則沒有這樣的限制;參數 resizable 表示 Window 在創建之後是否能夠調整大小。

為了實現 Window 一系列的屬性設置,一般常用的有如下方法。

Window 通過 setDraggable 方法來設置該 Window 是否可以拖拽。

public void setDraggable(boolean draggable) throws IllegalStateException

Window 通過 setMaximizable 方法來設置該 Window 是否可以最大化。

public void setMaximizable(boolean maximizable) throws IllegalStateException

當參數 maximizable 設置為 true 時,則在窗口的右上角出現可以最大化的按鈕。

Window 通過 setMinimizable 方法來設置該 Window 是否可以最小化。

public void setMinimizable(boolean minimizable) throws IllegalStateException

當參數 minimizable 設置為 true 時,則在窗口的右上角出現可以最小化的按鈕。

Window 通過 setResizable 方法來設置該 Window 是否可以調整大小。

public void setResizable(boolean resizable) throws IllegalStateException

當參數 resizable 設置為 true 時,則可以調整 Window 大小。

當 Window 被初始化后,默認為隱藏。只有當調用 show() 這個方法的時候,window 才會出現。如圖 11 所示。

public native void show()


圖 11. 初始化的 Window

Window 也同樣擁有 Panel 容器的特性。因此在 Window 的基礎上又擴展出來了如下 6 個常用的對話框,通過實現 MessageBox 類的不同方法,或者配置 MessageBox 來實現不同的功能。

(1) Yes/No 對話框

Yes/No 對話框是提示用戶是否進行接下來操作的確認框,當頁面彈出是,對話框後面的內容不可選。如圖 12 所示。


圖 12. Yes/No 對話框

MessageBox 通過 confirm 方法實現 Yes/No 對話框。

public static native void confirm(String title, String message, ConfirmCallback cb)

參數 title 表示 MessageBox 的標題,參數 message 表示消息體。

我們可以通過匿名內部類的方式創建實例 MessageBox.ConfirmCallback,並且實現 execute 方法。如代碼清單 2 所示,用戶點擊的 Yes 或 No 按鈕的 ID 會通過 execute 方法的參數傳入,方便對用戶的選擇做相應的操作。


清單 2. Yes/No 對話框
				MessageBox.confirm("Confirm", "Are you sure you want to do that?",     |-------10--------20--------30--------40--------50--------60--------70--------80--------9|  |-------- XML error:  The previous line is longer than the max of 90 characters ---------|    new MessageBox.ConfirmCallback()     {         public void execute(String btnID)       {           System.out.println("You press the button " + btnID);       }       });

(2)Prompt 對話框

Prompt 對話框提供了輸入單行文字的方式。如圖 13 所示。


圖 13. Prompt 對話框

MessageBox 通過 prompt 方法實現 Prompt 對話框。

public static native void prompt(String title, String message, PromptCallback cb)

參數 title 表示標題,message 表示消息體。我們可以通過匿名內部類的方式創建實例 MessageBox. PromptCallback,並且實現 execute 方法。其中參數 btnID 是 ok 或者 Cancel 按鈕的 ID,參數 text 是用戶所輸入的單行文本。如代碼清單 3 所示。


清單 3. Prompt 對話框
				MessageBox.prompt("Name", "Please enter your name:",        new MessageBox.PromptCallback()      {          public void execute(String btnID, String text)        {            System.out.println("You clicked the" +          btnID +" button and entered the text " + text));        }        });

(3) 多行輸入對話框

創建多行輸入對話框的方式與 Prompt,Confirm 對話框有些不同。對話框的配置信息通過 MessageBoxConfig() 的實例來實現。如代碼清單 4 所示。


清單 4. 多行輸入對話框
				MessageBox.show(     new MessageBoxConfig()     {         {           setTitle("Address");           setMsg("Please enter your address:");           setWidth(300);           setButtons(MessageBox.OKCANCEL);           setMultiline(true);           setCallback(new MessageBox.PromptCallback()         {             public void execute(String btnID, String text)           {              	 System.out.println("You clicked the" +            	 btnID +" button and entered the text " + text);           }           });         setAnimEl(button.getId());          }       });

setWidth(300) 設置了對話框的寬度。

setButtons(MessageBox.OKCANCEL) 設置了顯示的 OK 和 Cancel 按鈕。

SetMultiline(true) 則表示了多行輸入框。

setCallback(new MessageBox.PromptCallback()) 方法和 Prompt 對話框類似。不在此贅述。

顯示如圖 14 所示。


圖 14. 多行輸入對話框

(4) 分步進度條窗口

分步進度條用於顯示當前過程的運行進度。在本例中,我們通過定時器每 1 秒刷新一次進度條,當十秒結束后表示過程已經完成。示例代碼如代碼清單 5 所示。


清單 5. 分步進度條窗口
				MessageBox.show(     new MessageBoxConfig()     {         {           setTitle("Please wait...");           setMsg("Initializing...");           setWidth(240);           setProgress(true);           setClosable(false);           setAnimEl(button.getId());          }        });    //create bogus progress      for(int i=1;i < 12;i++)      {          final int j = i;          Timer timer = new Timer()        {            public void run()          {              if (j == 11)            {                MessageBox.hide();              } else {                       MessageBox.updateProgress(j * 10,                     "Loading item "  + j + " of 10... ");                     }            }          };          timer.schedule(i * 1000);        }

Timer 的構造函數如下所示。

Timer()

Timer 提供了一個定時控制功能,他通過 schedule 方法讓任務在指定時間后開始

public void schedule(int delayMillis)

也可以通過 scheduleRepeating 方法指定任務重複運行的時間間隔

public void scheduleRepeating(int periodMillis)

通過 cancel 方法來停止 Timer 。

public void cancel()

如上例所示,Timer 控制進度條,每隔 1 秒前進 1 格。對 MessageBoxConfig 設置 setProgress(true) 方法顯示進度條。同時設置 setClosable(false) 表示進度條窗口不可關閉。如圖 15 所示。


圖 15. 分步進度條窗口

(5) 等待進度條窗口

在不可預知運行狀態的情況下,也可以通過等待進度條來實現。等待進度條並不是無限運行下去。它只是顯示任務,或者進程等正在處於運行狀態,提供一個友好的方式讓用戶等待。當任務結束的時候,進度條消失。

實現無限進度條的代碼如代碼清單 6 所示。


清單 6. 等待進度條窗口
				MessageBox.show(     new MessageBoxConfig()     {         {           setMsg("Saving your data, please wait...");           setProgressText("Saving...");           setWidth(300);           setWait(true);           setWaitConfig(new WaitConfig()         {             {               setInterval(200);             }           });           setAnimEl(button.getId());         }       });       Timer timer = new Timer()     {         public void run()       {           MessageBox.hide();           showMessage("Done", "Your fake data was saved!");       }       };       timer.schedule(8000);

Timer 的使用方式已經在上例中介紹。本例中,Timer 控制進度條,當 8 秒之後,進度條通過 MessageBox.hide() 的方法被隱藏起來。

通過 setProgressText("Saving...") 方法設置進度條顯示文字。

通過 setWait(true) 方法設置 MessageBox 為等待進度條。

通過 setInterval(200) 方法設置進度條更新間隔時間,在設置之前必須先創建 WaitConfig 的實例。

如圖 16 所示


圖 16. 等待進度條窗口

(6)Alert 對話框

MessageBox 通過 alert 方法實現 Alert 對話框。

public static void alert(String message)

參數 message 表示要顯示的消息。如圖 17 所示。


圖 17. Alert 對話框

在 下載 GWTEXTDemo-all.zip 中的 WindowDemo.java 中實現了上述所有功能。





結束語

本文主要介紹了 Panel,Toobar,Menus ,Portal 和 Window 等 GUI 元素。接下來,我們會介紹如何在 Panel 裡布局,以及界面編程中經常使用的顯示結構化的,具有繼承關係的數據的方法,Tree 。(責任編輯:A6)



[火星人 ] GWT-Ext 體驗之旅,第 2 部分: 體驗 Panel 和 Window已經有730次圍觀

http://coctec.com/docs/linux/show-post-68877.html