内容


GWT-Ext 体验之旅,第 2 部分

体验 Panel 和 Window

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: GWT-Ext 体验之旅,第 2 部分

敬请期待该系列的后续内容。

此内容是该系列的一部分:GWT-Ext 体验之旅,第 2 部分

敬请期待该系列的后续内容。

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 的伸缩功能
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的拖拽功能
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对象
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 项
CheckItem项

ColorItem,如图 7 所示

图 7. ColorItem 项
ColorItem项
ColorItem项

DateItem,如图 8 所示

图 8. DateItem 项
DateItem项
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
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
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
初始化的Window

Window 也同样拥有 Panel 容器的特性。因此在 Window 的基础上又扩展出来了如下 6 个常用的对话框,通过实现 MessageBox 类的不同方法,或者配置 MessageBox 来实现不同的功能。

(1) Yes/No 对话框

Yes/No 对话框是提示用户是否进行接下来操作的确认框,当页面弹出是,对话框后面的内容不可选。如图 12 所示。

图 12. Yes/No 对话框
Yes/No对话框
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?",   
  new MessageBox.ConfirmCallback() 
  {   
    public void execute(String btnID) 
    {   
      System.out.println("You press the button " + btnID); 
    }   
  });

(2)Prompt 对话框

Prompt 对话框提供了输入单行文字的方式。如图 13 所示。

图 13. Prompt 对话框
Prompt对话框
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 对话框
Alert对话框
Alert对话框

下载 GWTEXTDemo-all.zip 中的 WindowDemo.java 中实现了上述所有功能。

结束语

本文主要介绍了 Panel,Toobar,Menus ,Portal 和 Window 等 GUI 元素。接下来,我们会介绍如何在 Panel 里布局,以及界面编程中经常使用的显示结构化的,具有继承关系的数据的方法,Tree 。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology, Web development, Open source
ArticleID=391149
ArticleTitle=GWT-Ext 体验之旅,第 2 部分: 体验 Panel 和 Window
publish-date=05222009