具有覆盖类型问题的 GWT 单元小部件

发布于 2024-10-12 19:01:11 字数 3371 浏览 8 评论 0 原文

我从 Google 开发人员指南 并进行了以下更改:

  • 使用覆盖层而不是 Java POJO
  • 使用 EditTextCell 编辑一列

令我惊讶的是,在运行代码时,单元格表向推入其中的覆盖对象添加了一个额外的属性。它们应该看起来像:

{"name":"John", "address":"123 Fourth Road"} {"name":"Mary", "address":"222 Lancer Lane"}

但它们看起来像:

{"name":"John", "address":"123 Fourth Road", "$H":1 } {"name":"Mary", "address":"222 Lancer Lane", "$H":2}

以下是演示该问题的修改后的代码:

import java.util.Arrays;
import java.util.List;

import com.google.gwt.cell.client.EditTextCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Overlay implements EntryPoint {

    private static class Contact extends JavaScriptObject {

        protected Contact() {}

        public static native Contact create(String name, String address) /*-{
            return {"name" : name , "address" : address};
        }-*/;
        public final native String getName() /*-{
            return this["name"];
        }-*/;   
        public final native void setName(String name) /*-{
            this["name"] = name;
        }-*/;
        public final native String getAddress() /*-{
            return this["address"];
        }-*/;   
        public final native void setAddress(String address) /*-{
            this["address"] = address;
        }-*/;
    }

    private static List<Contact> CONTACTS = Arrays.asList(
            Contact.create("John", "123 Fourth Road"),
            Contact.create("Mary", "222 Lancer Lane"));

    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {

        CellTable<Contact> table = new CellTable<Contact>();
        // Create name column.
        Column<Contact, String> nameColumn = new Column<Contact, String>(new EditTextCell()) {
            public String getValue(Contact object) {
                return object.getName();
            }
        };
        // Create address column.
        TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
            public String getValue(Contact contact) {
                return contact.getAddress();
            }
        };
        // Add the columns.
        table.addColumn(nameColumn, "Name");
        table.addColumn(addressColumn, "Address");      
        table.setRowCount(CONTACTS.size(), true);
        // Push the data into the widget.
        printList();
        table.setRowData(0, CONTACTS);      
        printList();        
        RootPanel.get().add(table);
    }

    private void printList() {
        for(Contact contact : CONTACTS) {
            GWT.log(new JSONObject(contact).toString());
        }
    }

}

我已经检查过它是导致该问题的可编辑列问题。如果我删除它,表格不会修改我的叠加层。

无论如何,这是一种非常奇怪的行为。如果您的小部件可以添加意外的属性,我认为使用覆盖层是不安全的。

以前有人遇到过这个问题吗?或者这个行为是否记录在任何地方?有什么提示可以解决吗?

多谢

I have taken the Cell Table example from google developer's guide and made the following changes:

  • Use overlays instead of Java POJOs
  • Use a EditTextCell to edit one column

For my surprise, when running the code the Cell Table is adding an extra property to the overlay objects pushed into it. They should look like:

{"name":"John", "address":"123 Fourth Road"}
{"name":"Mary", "address":"222 Lancer Lane"}

But instead they look like:

{"name":"John", "address":"123 Fourth Road", "$H":1}
{"name":"Mary", "address":"222 Lancer Lane", "$H":2}

Here is the modified code that demonstrates the issue:

import java.util.Arrays;
import java.util.List;

import com.google.gwt.cell.client.EditTextCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Overlay implements EntryPoint {

    private static class Contact extends JavaScriptObject {

        protected Contact() {}

        public static native Contact create(String name, String address) /*-{
            return {"name" : name , "address" : address};
        }-*/;
        public final native String getName() /*-{
            return this["name"];
        }-*/;   
        public final native void setName(String name) /*-{
            this["name"] = name;
        }-*/;
        public final native String getAddress() /*-{
            return this["address"];
        }-*/;   
        public final native void setAddress(String address) /*-{
            this["address"] = address;
        }-*/;
    }

    private static List<Contact> CONTACTS = Arrays.asList(
            Contact.create("John", "123 Fourth Road"),
            Contact.create("Mary", "222 Lancer Lane"));

    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {

        CellTable<Contact> table = new CellTable<Contact>();
        // Create name column.
        Column<Contact, String> nameColumn = new Column<Contact, String>(new EditTextCell()) {
            public String getValue(Contact object) {
                return object.getName();
            }
        };
        // Create address column.
        TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
            public String getValue(Contact contact) {
                return contact.getAddress();
            }
        };
        // Add the columns.
        table.addColumn(nameColumn, "Name");
        table.addColumn(addressColumn, "Address");      
        table.setRowCount(CONTACTS.size(), true);
        // Push the data into the widget.
        printList();
        table.setRowData(0, CONTACTS);      
        printList();        
        RootPanel.get().add(table);
    }

    private void printList() {
        for(Contact contact : CONTACTS) {
            GWT.log(new JSONObject(contact).toString());
        }
    }

}

I have checked that it is the editable column the one that causes the issue. If I remove it the table does not modify my overlays.

Anyway, this is a very weird behaviour. I don't feel it is safe to work with overlays if your widgets can add them unexpected properties.

Has anyone encountered this issue before or is this behaviour documented anywhere? Any hints to solve it?

Thanks a lot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一身软味 2024-10-19 19:01:11

此问题的正确答案已发布在 GWT 开发论坛中(链接):

$H 属性来自
实施
JavaScriptObject#hashCode() (在
com.google.gwt.cire.client.impl.Impl#getHashCode(Object))。

就您而言,这是由于
AbstractEditableCell 维护地图
他们的“查看数据”的价值键,
以及您对默认值的使用(我猜)
提供关键实现
(SimpleProvidesKey) 直接
返回该项目。

因此,渲染时,EditTextCell
调用 getViewData,它会查找
地图中的键(因此需要
键的哈希码,因此调用
hashCode),关键是你的 JSO
(因此有了新的 $H 属性)。

我相信提供 ProvidesKey
实施(在你的情况下,返回
例如 name 属性)到
Celltable 可以解决您的问题。

The correct answer to this issue was posted in the GWT development forum (link):

The $H property comes from the
implementation of
JavaScriptObject#hashCode() (in
com.google.gwt.cire.client.impl.Impl#getHashCode(Object)).

In your case, this is due to
AbstractEditableCell maintaining a map
of value keys to their "view data",
and your use (I guess) of the default
ProvidesKey implementation
(SimpleProvidesKey) which directly
returns the item.

So, when rendering, the EditTextCell
calls getViewData, which looks up the
key in the map (and thus needs the
hashcode of the key, hence the call to
hashCode), and the key is your JSO
(hence the new $H property).

I believe that giving a ProvidesKey
implementation (in you case, returning
the name property for instance) to the
Celltable would solve your issue.

柳絮泡泡 2024-10-19 19:01:11

我怀疑 CellTable 可以偷偷地编辑你的 JSON。检查 Firebug/Chrome_Developer_Tools/... 中的这些覆盖层,如果正常,则最有可能的错误在这一行:

GWT.log(new JSONObject(contact).toString());

JSONObject.toString 至少有两个问题: 将列表传递至/from JSNI 在 Web 模式下工作,但在托管模式下失败 & toString() 和 JSNI
在第二期中,有评论,根据你可以尝试这个:

GWT.log( (String) new JSONObject(contact) );

I doubt that CellTable can sneakily edit your JSONs. Check those overlays in Firebug/Chrome_Developer_Tools/... if they ok then most likely bug is in this line:

GWT.log(new JSONObject(contact).toString());

There are atleast two issues for JSONObject.toString: Passing List to/from JSNI works in web mode but fails in hosted mode & toString() and JSNI.
In second issue there is comment according to which you can try this:

GWT.log( (String) new JSONObject(contact) );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文