GWT中UiBinder是用来管理界面结构和样式的技术,下面是google开发文档中的实例


这是一个最简单的UiBinder构建界面的例子,只有html,没有widget,是一个xml文件

<!-- HelloWorld.ui.xml -->
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>
  <div>
    Hello, <span ui:field='nameSpan'/>.
  </div>
</ui:UiBinder>


与其相对应的有一个java类

public class HelloWorld extends UIObject {
  interface MyUiBinder extends UiBinder<DivElement, HelloWorld> {}
  private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
  @UiField SpanElement nameSpan;
  public HelloWorld() {
    setElement(uiBinder.createAndBindUi(this));
  }
  public void setName(String name) { nameSpan.setInnerText(name); }
}

创建一个HelloWorld实例,并执行setName方法,向nameSpan中插入数据

HelloWorld helloWorld = new HelloWorld();
// Don't forget, this is DOM only; will not work with GWT widgets
Document.get().getBody().appendChild(helloWorld.getElement());
helloWorld.setName("World");



这里解释一下UiBinder的用法:

1. UiBinder是用GWT工厂模式创建的,接口UiBinder<U,O>声明了两个参数:U指的是ui.xml中声明的根元素;O是指对应的java类名。

2. 任何一个在ui.xml文件中申明的object都可以利用fieldname在对应的Java文件中被使用。在这个例子中,<span>有个ui:field属性,在Java文件中,对应表现为用@Uifield注释,变量名为ui:field的值。

3. 这个HelloWorld实例继承了UIObject类,它还可以继承Widget,Composite等。注意,被标识注释@UiField的域默认是可视的,如果他们被binder创建实例了,他们不可以是private的。


下面是一个使用了Widget的UiBinder的实例

<!-- HelloWidgetWorld.ui.xml -->
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
  <g:HTMLPanel>
    Hello, <g:ListBox ui:field='listBox' visibleItemCount='1'/>.
  </g:HTMLPanel>
</ui:UiBinder>


对应的Java类

public class HelloWidgetWorld extends Composite {
  interface MyUiBinder extends UiBinder<Widget, HelloWidgetWorld> {}
  private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
  @UiField ListBox listBox;
  public HelloWidgetWorld(String... names) {
    // sets listBox
    initWidget(uiBinder.createAndBindUi(this));
    for (String name : names) {
      listBox.addItem(name);
    }
  }
}

new一个实例

// Use:
HelloWidgetWorld helloWorld =
  new HelloWidgetWorld("able", "baker", "charlie");


分析上面的例子:

1. 利用 ”g='urn:import:com.google.gwt.user.client.ui'" import gwt的包,用g标识

2. 根元素为HTMLPanel , 继承了Widget

3. uiBinder.createAndBindUi(this)创建根元素的实例

4. visibleItemCount属性对应ListBox中setVisibleItemCount(int)方法


接下来是一个使用Panel的例子


任何一个Panel(理论上,任何继承了HasWidgets接口的类)可以在uiBinder模板中使用,并且可以包含其他Panel

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'>
  <g:HorizontalPanel>
    <g:Label>Keep your ducks</g:Label>
    <g:Label>in a row</g:Label>
  </g:HorizontalPanel>
</ui:UiBinder>


有些GWT的Widget需要特殊的标记,这是一个DockLayoutPanel的例子

<g:DockLayoutPanel unit='EM'>
  <g:north size='5'>
    <g:Label>Top</g:Label>
  </g:north>
  <g:center>
    <g:Label>Body</g:Label>
  </g:center>
  <g:west size='10'>
    <g:HTML>
      <ul>
        <li>Sidebar</li>
        <li>Sidebar</li>
        <li>Sidebar</li>
      </ul>
    </g:HTML>
  </g:west>
</g:DockLayoutPanel>

1. DockLayoutPanel 的子元素<g:north size='5'>, <g:center>, 他们不可以有ui:field属性,因为在java类中是没有这些域的。

2. 需要注意的是,大多数的Panel都不可以将HTML直接放入,但是可以放入Widget中


下面是绑定Event Handlers的实例


一般情况下在java代码中写Event Handler是这样的:

public class MyFoo extends Composite {
  Button button = new Button();
  public MyFoo() {
    button.addClickHandler(new ClickHandler() {
      public void onClick ClickEvent event) {
        handleClick();
      }
    });
    initWidget(button);
  }
  void handleClick() {
    Window.alert("Hello, AJAX");
  }
}


在UiBinder模板对应的Java文件中,我们可以利用@UiHandler

public class MyFoo extends Composite {
  @UiField Button button;
  public MyFoo() {
    initWidget(button);
  }
  @UiHandler("button")
  void handleClick(ClickEvent e) {
    Window.alert("Hello, AJAX");
  }
}


Composite是一种可以包含其他Widget的Widget,具体可参考google-web-toolkit.googlecode