【问题标题】:Does the SimpleBeanEditorDriver support autoboxing?SimpleBeanEditorDriver 是否支持自动装箱?
【发布时间】:2014-11-21 01:37:30
【问题描述】:

我有一个简单的豆子:

public class SimpleBean implements Serializable {
    String stringMe;
    double autoboxMe;
    // ... boilerplate ...
}

我创建了一个实现编辑器的视图。

public class View extends Component implements Editor<SimpleBean> {

    @UiField
    HasValue<String> stringMeEditor;
    @UiField
    HasValue<Double> autoboxMeEditor;

    // boilerplate uibinder blabla
}

如果我运行此编辑器,无论是独立运行还是在树中运行,我只会在视图中收到字符串的值,双框保持为空。

如果我承担编写 LeafValueEditor 的负担,在 setValue() 方法中明确设置值,就会出现双打。

那么,问题出在哪里? SimpleBeanEditorDriver 是否不能自动装箱并且找不到匹配的编辑器字段?

更新:已要求提供实际代码。

这是真正的编辑器。此编辑器仅在 LeafValueEditor 就位时才有效。如果将 LVE 替换为简单的“编辑器”,它将不会呈现任何价值。

我知道如果值为 null,NPE 会出现问题,但可以通过 Validation 进行管理。

package de.srs.pen.portal.widgets.metadataeditor;

import com.google.gwt.activity.shared.Activity;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.user.client.ui.IsWidget;

import de.srs.pen.api.meta.xml.PageClip;
import de.srs.pen.portal.widgets.editors.HasDeleteHandlers;
import de.srs.pen.portal.widgets.utils.HasActivity;

public interface PageClipEditor
        extends Activity
{
    public interface View
            extends IsWidget, HasActivity<PageClipEditor>, LeafValueEditor<PageClip>, HasDeleteHandlers
    {

        void removeFromParent();

    }
}

这是View接口的实现。

package de.srs.pen.portal.widgets.metadataeditor;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.Widget;

import de.srs.pen.api.meta.xml.PageClip;
import de.srs.pen.portal.widgets.editors.EditorDeleteEvent;
import de.srs.pen.portal.widgets.editors.EditorDeleteEventHandler;

public class PageClipEditorView
        extends Composite
        implements PageClipEditor.View
{

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

    interface PageClipEditorViewUiBinder
            extends UiBinder<Widget, PageClipEditorView>
    {}

    private PageClipEditor activity;

    @UiField
    HasClickHandlers btnDelete;

    @UiField
    @Path("id")
    HasValue<String> idEditor;
    @UiField
    @Path("display")
    PageDisplayEnumEditor displayEditor;
    @UiField
    @Path("xPos")
    HasValue<Double> xPosEditor;
    @UiField
    @Path("yPos")
    HasValue<Double> yPosEditor;
    @UiField
    @Path("height")
    HasValue<Double> heightEditor;
    @UiField
    @Path("width")
    HasValue<Double> widthEditor;

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

    @Override
    public void setActivity(PageClipEditor activity) {
        this.activity = activity;
    }

    @Override
    public PageClipEditor getActivity() {
        return this.activity;
    }

    @Override
    public HandlerRegistration addDeleteHandler(EditorDeleteEventHandler handler) {
        return addHandler( handler, EditorDeleteEvent.TYPE );
    }

    @UiHandler("btnDelete")
    public void handleDelete(ClickEvent ev) {
        fireEvent( new EditorDeleteEvent() );
    }

    @Override
    public void setValue(PageClip value) {
        displayEditor.asEditor().setValue( value.getDisplay() );
        heightEditor.setValue( value.getHeight() );
        widthEditor.setValue( value.getWidth() );
        xPosEditor.setValue( value.getxPos() );
        yPosEditor.setValue( value.getyPos() );
        idEditor.setValue( value.getId() );
    }

    @Override
    public PageClip getValue() {
        PageClip clip = new PageClip( idEditor.getValue(),
                                      xPosEditor.getValue(), yPosEditor.getValue(),
                                      widthEditor.getValue(), heightEditor.getValue(),
                                      displayEditor.asEditor().getValue() );
        return clip;
    }
}

这是 uibinder 模板文件。

<!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:p="urn:import:de.srs.pen.portal.widgets.metadataeditor">
    <ui:with type="de.srs.pen.portal.widgets.metadataeditor.MetadataEditorText"
        field="res" />
    <ui:with type="de.srs.pen.portal.widgets.icons.WidgetIcons"
        field="icon" />

    <ui:style>

    </ui:style>
    <g:HTMLPanel>
        <g:Image ui:field="btnDelete" resource="{icon.circleCloseDeleteGlyph}"
            height="16px" width="16px" title="{res.pageclipDelete}" />
        <g:InlineLabel text="{res.pageclipName}" />
        <g:TextBox ui:field="idEditor" width="5em"/>
        <g:InlineLabel text="{res.pageclipDisplay}" />
        <p:PageDisplayEnumEditor ui:field="displayEditor" />
        <g:InlineLabel text="{res.pageclipXPos}" />
        <g:DoubleBox ui:field="xPosEditor" width="2.5em" />
        <g:InlineLabel text="{res.pageclipYPos}" />
        <g:DoubleBox ui:field="yPosEditor" width="2.5em" />
        <g:InlineLabel text="{res.pageclipHeight}" />
        <g:DoubleBox ui:field="heightEditor" width="2.5em" />
        <g:InlineLabel text="{res.pageclipWidth}" />
        <g:DoubleBox ui:field="widthEditor" width="2.5em" />
    </g:HTMLPanel>
</ui:UiBinder> 

最后,这是 PageClip 对象本身。

package de.srs.pen.api.meta.xml;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "clip", namespace = "urn:srs.pdx.metadata")
public class PageClip implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 5556156665068106790L;

    @XmlAttribute(required=true)
    protected String id;

    @XmlAttribute(name = "xPos", required = true)
    protected double xPos;

    @XmlAttribute(name = "yPos", required = true)
    protected double yPos;

    @XmlAttribute(name = "width", required = true)
    protected double width;

    @XmlAttribute(name = "height", required = true)
    protected double height;

    @XmlAttribute(name ="display", required = false)
    protected String display;

    public PageClip() {
    }

    public PageClip( String id, double xPos, double yPos, double width, double height ) {
        super();
        this.id = id;
        this.xPos = xPos;
        this.yPos = yPos;
        this.width = width;
        this.height = height;
    }

    public PageClip( String id, double xPos, double yPos, double width, double height, String display ) {
        this(id, xPos, yPos, width, height);
        this.display = display;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public double getxPos() {
        return xPos;
    }

    public void setxPos(double xPos) {
        this.xPos = xPos;
    }

    public double getyPos() {
        return yPos;
    }

    public void setyPos(double yPos) {
        this.yPos = yPos;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public String getDisplay() {
        return display;
    }

    public void setDisplay(String display) {
        this.display = display;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append( "PageClip [id=" )
            .append( id )
            .append( ", xPos=" )
            .append( xPos )
            .append( ", yPos=" )
            .append( yPos )
            .append( ", width=" )
            .append( width )
            .append( ", height=" )
            .append( height )
            .append( ", display=" )
            .append( display )
            .append( "]" );
        return builder.toString();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((display == null) ? 0 : display.hashCode());
        long temp;
        temp = Double.doubleToLongBits( height );
        result = prime * result + (int)(temp ^ (temp >>> 32));
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        temp = Double.doubleToLongBits( width );
        result = prime * result + (int)(temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits( xPos );
        result = prime * result + (int)(temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits( yPos );
        result = prime * result + (int)(temp ^ (temp >>> 32));
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if( this == obj ) {
            return true;
        }
        if( obj == null ) {
            return false;
        }
        if( !(obj instanceof PageClip) ) {
            return false;
        }
        PageClip other = (PageClip)obj;
        if( display == null ) {
            if( other.display != null ) {
                return false;
            }
        }
        else if( !display.equals( other.display ) ) {
            return false;
        }
        if( Double.doubleToLongBits( height ) != Double.doubleToLongBits( other.height ) ) {
            return false;
        }
        if( id == null ) {
            if( other.id != null ) {
                return false;
            }
        }
        else if( !id.equals( other.id ) ) {
            return false;
        }
        if( Double.doubleToLongBits( width ) != Double.doubleToLongBits( other.width ) ) {
            return false;
        }
        if( Double.doubleToLongBits( xPos ) != Double.doubleToLongBits( other.xPos ) ) {
            return false;
        }
        if( Double.doubleToLongBits( yPos ) != Double.doubleToLongBits( other.yPos ) ) {
            return false;
        }
        return true;
    }


}

【问题讨论】:

  • 您是否尝试将 @Path("autoboxMe") 设置为 autoboxMeEditor ?因为您的 bean 和视图的字段名称不同。
  • 编辑器框架支持查找具有属性和属性编辑器名称的小部件。并且字符串值已正确设置,因此不能成为原因。但是是的:我也尝试过设置@Path - 没有区别。

标签: gwt editor


【解决方案1】:

是的,支持自动装箱,但您应该非常小心,这实际上是您想要的 - 如果 autoBoxMeEditor.getValue() 返回 null,那么当您调用 driver.flush() 时将会有一个 NullPointerException

话虽如此,HasValue 不是编辑器,并且您的“bean”没有 getter 和 setter - 这两个事实应该意味着您的编辑器都不应该工作,而不仅仅是字符串。如果你用真实代码更新问题,我会稍后再回来查看。


来自您的编辑:

这是真正的编辑器。此编辑器仅在 LeafValueEditor 就位时才有效。如果将 LVE 替换为简单的“编辑器”,它将不会呈现任何价值。

这就是问题所在,这就是为什么它似乎在没有实际说明您的子编辑器是编辑器的情况下工作:

@Override
public void setValue(PageClip value) {
    displayEditor.asEditor().setValue( value.getDisplay() );
    heightEditor.setValue( value.getHeight() );
    widthEditor.setValue( value.getWidth() );
    xPosEditor.setValue( value.getxPos() );
    yPosEditor.setValue( value.getyPos() );
    idEditor.setValue( value.getId() );
}

您不应该编写该方法,但是因为 a) 您没有将您的编辑器称为 Editors,并且 b) 您将父级设为 LeafValueEditor,所以您必须这样做。

首先,LeafValueEditor 是什么意思?简而言之,您的类型是说“我代表编辑树中的一些叶子 - 不要费心看我的孩子(即字段)来弄清楚如何绑定子编辑器”。如果您实际上实现了Editor&lt;PageClip&gt;,编辑器系统会查看该类,并尝试找到任何编辑器字段。

接下来,由于您没有任何编辑器字段,因此移至Editor 也无济于事!不要将您的字段称为 HasValue,而是按它们的真实类型来引用它们。这包括接口 LeafValueEditor(还记得上面的这个吗?),因此 String 和 double 将正确绑定。


您可能会遇到的一个未来问题,因为您没有共享驱动程序设置的代码:确保您在驱动程序声明中引用编辑器实现,而不是视图界面.您必须这样做,以便驱动程序知道它正在与哪个 impl 对话,以及它预期具有哪些子字段(以及此类子编辑器)。

【讨论】:

  • 我离开了 getter 和 setter 以保持问题简短,我的代码包含所有 getter 和 setter。但是 HasValue is not an editor 给了我一些想法:如果 ui.xml 将 TextBox 作为真实字段,这是否相关?并且:为什么它可以与 HasValue 一起使用?
  • @thst, HasValue&lt;String&gt; 本身不是编辑器,因此无法使用。您必须在某处将其称为真正的编辑器,或者自己调用 setValue。如果 HasValue 确实有效,并且如果编辑器框架不理解 double->Double,则会收到子编辑器与 bean 中的属性不匹配的错误。
  • 关于驱动程序中的接口:我已经发现了困难的方式 :-) 当然,如果您考虑一下,这是有道理的。我会尝试用编辑器类型替换接口,看看会发生什么。
  • 该死。你说的太对了,你不会相信我研究那件事多久了:-/
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-22
  • 1970-01-01
  • 2011-12-25
  • 2011-10-12
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多