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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2822273/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:00:17  来源:igfitidea点击:

How to combine multiple uiBinder-based widgets?

javaxmlgwtwidgetuibinder

提问by jprusakova

I need to insert a [number of] uiBinder-based widgets into another one, at a particular spot. The inserted widget has a somewhat complicated layout, so I am trying to define it in HTML.

我需要在特定位置将 [多个] 基于 uiBinder 的小部件插入到另一个小部件中。插入的小部件布局有些复杂,因此我尝试在 HTML 中定义它。

referencePanel.add(...) fails with java.lang.IllegalStateException: This widget's parent does not implement HasWidgets. Don't know which widget's parent it's unhappy about - innerPanel or referencePanel.

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

If the ReferenceUI object is added to RootPanel, and then it's added to the bottom of the page. But if it's added to RootPanel first, then there is a JavaScriptException Code 3 (HIERARCHY_REQUEST_ERR) when added to referencePanel.

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

Any suggestions?

有什么建议?

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);
        }
}

 

 

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;
    }
}

ReferenceUI.ui.xml

参考UI.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>

AppUIDemo.ui.xml

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>

回答by Wesley

I'll start with the fix, then move on to explain it afterward.

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

Fixing the problem

解决问题

The easiest way to fix this problem is as follows. Here's your code:

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

HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(innerPanel);

Replace that with the following code. Note that only the last line has changed.

将其替换为以下代码。请注意,只有最后一行发生了变化。

HTMLPanel innerPanel = reference.getRefPanel();
innerPanel.getElement().setId(HTMLPanel.createUniqueId());
referencePanel.add(reference);

This way, you are adding the Compositeobject. There will be no difference to the user, as the HTMLPanel(your innerPanel) will be directly attached into the document.

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



Some background

一些背景

Adding a widget to a complex panel

向复杂面板添加小部件

When you add a widget to a complex panel (a panel that holds more than one child widget), four things happen one after the other:

当您将一个小部件添加到一个复杂的面板(一个包含多个子小部件的面板)时,四件事情会接连发生:

  1. The widget is told to remove itself from its current parent
  2. The panel adds the widget to its list of children
  3. The panel adds the widget to the document
  4. The widget is told to set the panel as its new parent
  1. 小部件被告知从其当前父级中删除自身
  2. 面板将小部件添加到其子项列表中
  3. 面板将小部件添加到文档中
  4. 小部件被告知将面板设置为其新的父级

Telling a widget to remove itself from its parent

告诉小部件从其父级中移除自己

When a child is told to remove itself from its parent, one of the following occurs:

当一个孩子被告知从其父级中移除自己时,会发生以下情况之一:

  • If the widget does not have a parent, it does nothing
  • If the widget is the child of a panel that implements HasWidgets, the widget tells the panel to remove that widget
  • Otherwise, the widget throws IllegalStateExceptionwith message "This widget's parent does not implement HasWidgets
  • 如果小部件没有父级,则它什么都不做
  • 如果小部件是实现 的面板的子HasWidgets部件,则小部件会通知面板删除该小部件
  • 否则,小部件将抛出IllegalStateException消息“此小部件的父级未实现 HasWidgets

Composite widgets

复合小部件

When calling initWidget(Widget), the widget's parent is set to the Compositeobject.

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

The problem

问题

When you try to add innerPanel, it is told to remove itself from its current parent. innerPanelis actually the root of your UiBinder template. Its parent is a Compositeobject (specifically, ReferenceUI). This results in the exception being thrown, as Compositedoes not implement HasWidgetsand does not support removing its widget.

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

回答by Igor Klimer

Unfortunately, IIRC you can't set an id for a Widget in UiBinder's code (I think you can only for normal HTML). So you are left with setting the correct id via someWidget.getElement().setId()(like you did in the code above).

不幸的是,IIRC 不能在 UiBinder 的代码中为小部件设置 id(我认为你只能为普通的 HTML)。所以你需要通过设置正确的id someWidget.getElement().setId()(就像你在上面的代码中所做的那样)。

What's missing now, I think, is a placeholder (a div, span, whatever) with the correct id in the HTMLPanel referencePanel, like so:

我认为现在缺少的是一个占位符(一个 div、span 等等),在 中具有正确的 id HTMLPanel referencePanel,如下所示:

<g:HTMLPanel ui:field="referencePanel">
    <div ui:field="referencePanelInner" />
</g:HTMLPanel>

And in AppUIDemo:

并在AppUIDemo

@UiField
DivElement referencePanelInner;
// ...
public AppUIDemo() {
    // ...
    referencePanelInner.setId(reference.getRefPanelId());
}

...unless you want to add the ReferenceUI directly into referencePanel- in which case you should just use a FlowPanel:)

...除非您想将 ReferenceUI 直接添加到referencePanel- 在这种情况下,您应该只使用FlowPanel:)

PS: IMHO, you should generate and set the unique id for the ReferenceUI.refPanelfrom the ReferenceUIclass (and expose the id) - that way you don't mess with the widget's "internals" from some external widgets.

PS:恕我直言,你应该ReferenceUI.refPanelReferenceUI类中生成并设置唯一的ID (并公开ID) - 这样你就不会从一些外部小部件中弄乱小部件的“内部”。



OK, I think I got it. The IllegalStateExceptionexception is being thrown because you are adding ReferenceUI.refPanel(or ReferenceUI.referencePanel, I don't know which is the current name) to AppUIDemo(ReferenceUIobviously doesn't implement HasWidgets) - when you should be adding the whole ReferenceUI referencecomposite :) I don't know why you did it this way in the first place (maybe because of the whole mess with the ids), but the code should look something like this:

好的,我想我明白了。该IllegalStateException异常被抛出,因为要添加ReferenceUI.refPanel(或ReferenceUI.referencePanel,我不知道这是目前的名称)AppUIDemoReferenceUI显然没有实现HasWidgets) -当你应该加入整个ReferenceUI reference复合:)我不知道你为什么这样做首先是这种方式(可能是因为 id 弄得一团糟),但代码应该是这样的:

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

        referencePanel.add(reference);
    }