这个错误 "SEVERE: Server sent Vaadin 6 style updates for Connector...but this is not a Vaadin 6 Paintable" 在 Vaadin 7 中意味着什么?

What does this error "SEVERE: Server sent Vaadin 6 style updates for Connector...but this is not a Vaadin 6 Paintable" mean in Vaadin 7?

我正在学习Vaadin 7,我正在阅读Vaadin 7 CookBook。其实我在第4章,请问有没有人遇到过这样的问题:

我在浏览器控制台中收到以下错误:

SEVERE: Server sent Vaadin 6 style updates for ChromaHashPasswordFieldConnector (3) but this is not a Vaadin 6 Paintable

当我渲染这个时 UI:

public class ChromaHashUI extends UI {

    @WebServlet(value = "/*", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = ChromaHashUI.class, widgetset = "com.example.chromahash.widget.Chapter_4___custom_widgets___creating_a_chroma_hash_password_fieldWidgetset")
    public static class Servlet extends VaadinServlet {
    }

    @Override
    protected void init(VaadinRequest request) {
        VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        layout.setSpacing(true);
        setContent(layout);

        layout.addComponents(new ChromaHashPasswordField(), new ChromaHashPasswordField());
    }

}

两个 ChromaHashPasswordField 组件是基于 GWT 的自定义小部件,代码如下:

ChromaHashPasswordField 服务器端组件:

public class ChromaHashPasswordField extends com.vaadin.ui.PasswordField {

    public ChromaHashPasswordField() {
    }

    @Override
    public ChromaHashPasswordFieldState getState() {
        return (ChromaHashPasswordFieldState) super.getState();
    }

    @Override
    public String getValue() {
        return super.getValue();
    }

    @Override
    public void setValue(String value) {
        getState().text = value;
    }
}

ChromaHashPasswordFieldWidget 客户端组件:

public class ChromaHashPasswordFieldWidget extends Composite {

    public static final String CLASSNAME = "chromahashpasswordfield";

    private PasswordTextBox textBox = new PasswordTextBox();
    private HTML chromaHashStripes = new HTML();
    private HorizontalPanel panel = new HorizontalPanel();
    private int numberStripes = 3;

    public ChromaHashPasswordFieldWidget() {
        initWidget(panel);
        setStyleName(CLASSNAME);
        panel.add(textBox);
        panel.add(chromaHashStripes);
    }

    private String[] getChromaHash(String text, int numberStripes) {
        String salt = "du467e4aSdfe";
        text += salt;
        String[] colors = new String[numberStripes];

        int hash;
        int part = text.length() / numberStripes;
        for (int i = 0; i < numberStripes; i++) {
            hash = text.substring(part * i, 
                                 (part * i) + part).hashCode();
            colors[i] = "#" + intToRGB(hash);
        }
        return colors;
    }

    public String intToRGB(int i) {
        String RGB = Integer.toHexString(((i >> 16) & 0xFF))
                   + Integer.toHexString(((i >> 8) & 0xFF))
                   + Integer.toHexString((i & 0xFF));
        while (RGB.length() < 6) {
            RGB += "0";
        }       
        return RGB;
    }

    public void updateChromaHashStripes() {
        String[] chromaHash = getChromaHash(getText(), numberStripes);
        int height = 18;
        int width = 6;

        String htmlStripes = "<div style=\"margin: 3px;\">";
        for (int i = 0; i < numberStripes; i++) {
            htmlStripes += "<div style=\"background-color: "+ chromaHash[i] + ";"
                                      + " float: left; height: "+ height + "px;"
                                      + " width: "+ width +"px;\">" 
                          +"</div>";
        }
        htmlStripes += "</div>";
        chromaHashStripes.setPixelSize(height * 2, width * numberStripes);
        chromaHashStripes.setHTML(htmlStripes);
    }

    public String getText() {
        return textBox.getText();
    }

    public void setText(String text) {
        textBox.setText(text);
    }

    public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
        return textBox.addKeyUpHandler(handler);
    }

}

ChromaHashPasswordFieldState组件的共享状态:

public class ChromaHashPasswordFieldState extends com.vaadin.shared.ui.textfield.AbstractTextFieldState {
    // initializer block, overrides AbstractTextFieldState's ones       
    {
        primaryStyleName = null;
    }

}

ChromaHashPasswordFieldConnector 连接器:

@Connect(ChromaHashPasswordField.class)
public class ChromaHashPasswordFieldConnector extends AbstractComponentConnector {

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

    public ChromaHashPasswordFieldConnector() {
        getWidget().addKeyUpHandler(new KeyUpHandler() {
            @Override
             public void onKeyUp(KeyUpEvent event) {
               getWidget().updateChromaHashStripes();
             }
        });
    }

    @Override
    protected Widget createWidget() {
        return GWT.create(ChromaHashPasswordFieldWidget.class);
    }

    @Override
    public ChromaHashPasswordFieldWidget getWidget() {
        return (ChromaHashPasswordFieldWidget) super.getWidget();
    }

    @Override
    public ChromaHashPasswordFieldState getState() {
        return (ChromaHashPasswordFieldState) super.getState();
    }

    @Override
    public void onStateChanged(StateChangeEvent stateChangeEvent) {
        super.onStateChanged(stateChangeEvent);
        final String text = getState().text;
        getWidget().setText(text);
        getWidget().updateChromaHashStripes();
    }

}

当我编译和 运行 项目时,一切都按预期工作,正如您从这个屏幕截图中看到的那样:

但是在控制台中出现了我上面提到的那个错误。它与不同的 Vaadin 版本有关吗?我可以修复此错误还是与 Vaadin/GWT 相关?

感谢关注!

您在服务器端扩展了 PasswordField class,它扩展了 AbstractTextField 并且 AbstractTextField 实现了 com.vaadin.ui.LegacyComponent 接口。 LegacyComponent 更容易将 Vaadin 组件从 Vaadin 6 转换为 Vaadin 7,并且大多数核心组件都以这种方式转换。

当服务器端 class 实现 LegacyComponent 接口时,该 class 的连接器必须实现 com.vaadin.client.Paintable 接口。您看到错误消息是因为您的连接器未实现该接口。在 Paintable.updateFromUIDL 中,您应该处理来自 LegacyComponent.paintContent 的更改。