gwt中uibinder的动态值

时间:2012-07-14 23:07:40

标签: gwt uibinder

我是GWT的新手并尝试制作一个试图继承复合小部件的页面,但复合小部件的值是动态的。

我的主页有点像:

         .....
         .....
         <g:Button>Open composite widget</g:button>
         .....
         .....

正在打开另一个弹出式面板,如:

         .....
         <table>
            <tr><td>Top: <myCompany:userMeasurementUnit/> </td></tr>
            <tr><td>Bottom: <myCompany:userMeasurementUnit/> </td></tr>
            <tr><td>Left: <myCompany:userMeasurementUnit/> </td></tr>
            <tr><td>Right: <myCompany:userMeasurementUnit/> </td></tr>
        </table>

上面应该告诉我们

         top (cm)
         bottom (cm)
         left (cm)
         right (cm)

但我不知道如何将值从主页传递到自定义小部件,即usermeasurementunit

          <myCompany:userMeasurementUnit/>

我的usermeasurementunit类似于:

UiBinder的:

     <htmlpanel tag="span" ui:field="unit"/>

并且composit小部件是

      usermeasurementunit extends Composite {

       public usermeasurementunit(){
           initwidget...
       }

       public onload() { 
         ...
       }

       }

现在我想在点击按钮时传递任何测量单位厘米或英寸或米。我尝试使用事件总线,但它没有帮助,因为当我点击按钮popuppanel不在屏幕上,它没有捕捉事件。如果你们中的任何一个人能够帮助我,我会非常感激,因为我真的在努力解决这个问题。

亲切的问候

2 个答案:

答案 0 :(得分:13)

首先,您需要了解GWT中的对象实例化流程。

他们称之为“延迟绑定”,而不是“动态绑定”。

Uibinder xml文件是一个布局模板。并且它背后的JAva源bean在通用编程术语中被称为“代码隐藏”。

uibinder布局模板的作用或目的是卸载布局(在互联网上许多非英语程序员编写“布局”,尽管语法有趣,但是同样的事情)因此代码隐藏可以专注于控制布局的响应。

这类似于MVP的态度。查看与表示控件分离的实现。您可以自由编写代码隐藏错误,甚至无需确切知道这些字段的布局位置。您甚至可以简单地提供一个模板,其中ui元素没有正确布局,以便首先专注于您的代码隐藏。也许在那之后。一个用于移动设备的uibinder模板,另一个用于桌面设备 - 但是它们可以共享相同的代码隐藏。

uibinder模板显示的值在uibind期间一劳永逸地确定。 uibinder字段没有动态绑定到代码隐藏中声明的对象/变量的不断变化的值。

要在uibind之后动态更改/传播uibinder字段的值,您必须在代码隐藏中故意设置其值或编写侦听器以检测其更改。

public class Graceland {

  @UiField
  Label pressure;

  @UiField
  Button reset;

  public void setPressure(int value) {
    pressure.setText(value);
  }

  @UiHandler("reset")
  void nameDoesNotMatter(ClickEvent ev) {
    pressure.setText(default);
  }
}

GWT.create()在编译期间为模板生成Java源代码。 GWT.create不是运行时函数。

@ uiField和@UiHandler在uibind期间绑定到模板中的uifield。

uibind()的作用大部分不是运行时,而是编译时。虽然,它的终结性是在运行时实现的,但构造对象的所有javascript代码和相应的值都是在编译期间生成的,并且在运行时uibind期间只执行一次。

因此,目的不是要完全取代代码隐藏的动态角色,而只是为了让它免于布局任务,这样我们程序员就可以拥有一块干净的代码隐藏用布局的意大利面来源尽可能少地弄脏。

但是,如果您希望在绑定时“动态”影响uibinder字段的值,那么Ui:with就是您的朋友。

package z.mambazo;
public class Graceland {
  ....
  String initialPressure(){
    /* "dynamically" obtain the pressure from the
     * pressure gauge in the petroleum distillation stack
     * during uibind
     */
  }
}

Graceland.ui.xml:

<ui:UiBinder blah...blah>
  <ui:with type="z.mambazo" field="zulu"/>
  <g:VerticalPanel>
    <g:Label
      ui:field="pressure"
      text="the temperature is :{zulu.initialPressure}"/>
  </g:VerticalPanel>
</ui:UiBinder>

ui:with bean不一定是模板的代码隐藏。 ui:with bean有一个无参构造函数,或者你必须提供带有与构造函数参数对应的属性的ui:with标记。

您必须注意,为了使用ui:with,必须在value属性中声明init值,而不是在标记文本中声明。

<g:Label
  ui:field="pressure"
  text="the temperature is : {zulu.initialPressure}"/>

<g:Label ui:field="pressure">
  the temperature is : {zulu.initialPressure}
</g:Label>

第二种方式,只是按原样重现文本。

但是,您也可以这样做:

<g:HtmlPanel>
  the temperature is :&nbsp;
  <g:Label ui:field="pressure"
    text="{zulu.initialPressure}"/>
</g:HtmlPanel>

另外,请注意,所有GWT UI Java代码,甚至是临时生成的代码,都被翻译成浏览器Javascript。所以,无论你用ui引用什么类:必须使用Java源代码而不是Java字节代码。并且这些源代码不能在调用链调用字节代码的任何时候。

答案 1 :(得分:1)

您需要的是shared resources。这是一个例子:

MeasurementConstants.java:

package com.acme.client;

public class MeasurementConstants {

    private final String measurementUnit;

    public MeasurementConstants(String measurementUnit) {
        this.measurementUnit = measurementUnit;
    }

    public String measurementUnit() {
        return measurementUnit;
    }

}

UiBinderMeasurement.java:

package com.acme.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;

public class UiBinderMeasurement extends Composite {

    private static UiBinderI18nUiBinder uiBinder = GWT
            .create(UiBinderI18nUiBinder.class);
    private MeasurementConstants constants;

    interface UiBinderI18nUiBinder extends UiBinder<Widget, UiBinderMeasurement> {
    }

    public UiBinderMeasurement(MeasurementConstants constants) {
        this.constants = constants;
        initWidget(uiBinder.createAndBindUi(this));
    }

    @UiFactory
    public MeasurementConstants getConstants() {
        return constants;
    }

}

UiBinderMeasurement.ui.xml:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui">

    <ui:with type="com.acme.client.MeasurementConstants" field="constants"></ui:with>

    <g:HTMLPanel>
        <table>
            <tr><td><g:Label text="Top ({constants.measurementUnit}):" /> </td></tr>
            <tr><td><g:Label text="Bottom ({constants.measurementUnit}):" /> </td></tr>
            <tr><td><g:Label text="Left ({constants.measurementUnit}):" /> </td></tr>
            <tr><td><g:Label text="Right ({constants.measurementUnit}):" /> </td></tr>
        </table>
    </g:HTMLPanel>
</ui:UiBinder>

现在你可以这样称呼它:

new UiBinderMeasurement(new MeasurementConstants("cm"))