如何组合多个基于uiBinder的小部件?

jpr*_*ova 6 java xml gwt widget uibinder

我需要在一个特定的位置插入一个[基于uiBinder的小部件]到另一个小部件.插入的小部件有一个有点复杂的布局,所以我试图用HTML定义它.

referencePanel.add(...)因java.lang.IllegalStateException而失败:此小部件的父级未实现HasWidgets.不知道哪个小部件的父级不满意 - innerPanel或referencePanel.

如果将ReferenceUI对象添加到RootPanel,然后将其添加到页面底部.但如果它首先添加到RootPanel,那么在添加到referencePanel时会出现JavaScriptException Code 3(HIERARCHY_REQUEST_ERR).

有什么建议?

public class AppUIDemo extends Composite {
    @UiTemplate("AppUIDemo.ui.xml")
    interface AppUIDemoUiBinder extends UiBinder<Widget, AppUIDemo> {
    }

    @UiTemplate("ReferenceUI.ui.xml")
    interface ReferenceUIUiBinder extends
            UiBinder<Widget, ReferenceUI> {
    }

    private static AppUIDemoUiBinder uiBinder = GWT
            .create(AppUIDemoUiBinder.class);
    private static ReferenceUIUiBinder refUIBinder = GWT
            .create(ReferenceUIUiBinder.class);

    @UiField
    FlowPanel referencePanel;

    public AppUIDemo() {
            initWidget(uiBinder.createAndBindUi(this));
            ReferenceUI reference = new ReferenceUI(refUIBinder);

            HTMLPanel innerPanel = reference.getRefPanel();
            innerPanel.getElement().setId(HTMLPanel.createUniqueId());
            referencePanel.add(innerPanel);
        }
}
Run Code Online (Sandbox Code Playgroud)

 

public class ReferenceUI extends Composite {

    interface ReferenceUIUiBinder extends
            UiBinder<Widget,ReferenceUI> {
    }

    private static ReferenceUIUiBinder uiBinder = GWT
            .create(ReferenceUIUiBinder.class);


    @UiField
HTMLPanel refPanel;

    public ReferenceUI() {
        initWidget(uiBinder.createAndBindUi(this));
    }

    public CreditReferenceUI(final UiBinder<Widget, CreditReferenceUI> binder) {
        initWidget(binder.createAndBindUi(this));
    }

    public HTMLPanel getRefPanel() {
        return refPanel;
    }
}
Run Code Online (Sandbox Code Playgroud)

ReferenceUI.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"
    xmlns:gwittir="urn:import:com.totsp.gwittir.client.ui">
            <g:HTMLPanel ui:field="referencePanel">
            <table>
            <tr>
                <td>
                    <b>First Name</b></td>
                <td>
                    <b>Last Name</b></td>
                <td>
                    <b>Phone</b></td>
                <td>
                    <b>Fax</b></td>
            </tr>
            <tr>
                <td>
                    <gwittir:TextBox ui:field="referenceFirstName" styleName="input"/></td>
                <td>
                    <gwittir:TextBox ui:field="referenceLastName" styleName="input"/></td>
                <td>
                    <table><tr>
            <td> ( </td> <td>
                <gwittir:TextBox ui:field="referencePhoneAreaCode" styleName="input" maxLength="3"/></td>
                <td> ) </td> <td>
                <gwittir:TextBox ui:field="referencePhoneNumber" styleName="input" maxLength="7"/></td>
            <td> # </td> <td>
                <gwittir:TextBox ui:field="referencePhoneExtension" styleName="input" maxLength="25"/></td>
        </tr></table></td>
                <td>
                     <table><tr>
            <td> ( </td> <td>
                <gwittir:TextBox ui:field="referenceFaxAreaCode" styleName="input" maxLength="3"/></td>
                <td> ) </td> <td>
                <gwittir:TextBox ui:field="referenceFaxNumber" styleName="input" maxLength="7"/></td>
        </tr></table></td>
                </tr>
            <tr>
                <td style="text-align:right">
                    <b>Address: </b> Street</td>
                <td>
                    <gwittir:TextBox ui:field="referenceStreet" styleName="input"/></td>
                <td colspan="2" style="width:50%">
                    <table><tr><td>   City</td>
                    <td><gwittir:TextBox ui:field="referenceCity" styleName="input" maxLength="25"/></td>
                    <td> State </td>
                    <td class="state"><gwittir:TextBox ui:field="referenceState" styleName="input" maxLength="2"/></td>
                    <td> ZIP</td>
                    <td><gwittir:TextBox ui:field="referenceZIP" styleName="input" maxLength="9"/></td></tr></table>
                </td>
            </tr>
        </table>
    </g:HTMLPanel>
</ui:UiBinder>
Run Code Online (Sandbox Code Playgroud)

AppUIDemo.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"
    xmlns:gwittir="urn:import:com.totsp.gwittir.client.ui">
    <g:HTMLPanel ui:field="basePanel">
        <!--  <div id="MainContent">  -->
        <p><h2><b>Application Demo</b></h2></p>

        <g:FlowPanel ui:field="referencePanel">
        </g:FlowPanel>
    </g:HTMLPanel>
</ui:UiBinder>
Run Code Online (Sandbox Code Playgroud)

Wes*_*ley 13

我将从修复开始,然后继续解释它.

解决问题

解决此问题的最简单方法如下.这是你的代码:

HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(innerPanel);
Run Code Online (Sandbox Code Playgroud)

用以下代码替换它.请注意,只有最后一行已更改.

HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(reference);
Run Code Online (Sandbox Code Playgroud)

这样,您就是要添加Composite对象.用户没有区别,因为HTMLPanel(您的innerPanel)将直接附加到文档中.


一些背景

将小部件添加到复杂面板

将窗口小部件添加到复杂面板(包含多个子窗口小部件的面板)时,会依次发生四件事:

  1. 小部件被告知要从当前父级中删除自己
  2. 该面板将小部件添加到其子级列表中
  3. 面板将小部件添加到文档中
  4. 小部件被告知将面板设置为新的父级

告诉小部件将其自身从父级移除

当告知孩子将其自己从父母身上移除时,会发生以下情况之一:

  • 如果窗口小部件没有父窗口,则不执行任何操作
  • 如果窗口小部件是实现的面板的子HasWidgets窗口,则窗口小部件会告诉面板删除该窗口小部件
  • 否则,窗口小部件将抛出IllegalStateException消息"此窗口小部件的父窗口未实现HasWidgets

复合小部件

调用时initWidget(Widget),窗口小部件的父级设置为该Composite对象.

问题

当您尝试添加时innerPanel,会告知它将其自身从当前父项中删除.innerPanel实际上是UiBinder模板的根目录.它的父亲是一个Composite对象(具体而言ReferenceUI).这会导致异常被抛出,因为Composite没有实现HasWidgets,也不支持删除它的小部件.