使用Vaadin 7.4.9 - 如何从网格中删除数据

时间:2017-09-06 14:38:49

标签: java grid vaadin

我需要从网格(容器)中删除数据,然后我需要刷新行。我怎么能这样做?

Grid grid = new Grid();
IndexedContainer container = new IndexedContainer();
grid.setContainerDataSource(container);
container.addContainerProperty("firstNumber", Integer.class, 0);
container.addContainerProperty("secondNumber", Integer.class, 0);

container.addItem(1);

Item item = container.getItem(1);
int firstNumber = item.getItemProperty("firstNumber").setValue("1");

item = container.getItem(1);
int secondNumber = item.getItemProperty("secondNumber").setValue("2");

现在我尝试仅更改单元格而不删除项目。我的代码是

container.addValueChangeListener(e -> {

         Item item = container.getItem(35);
         item.getItemProperty("Person5").setValue("SS");

         grid.recalculateColumnWidths();
         grid.clearSortOrder();
         grid.refreshAllRows();

     });

但我也有错误...... :(

enter image description here

Morfic的信息:

我需要更改网格单元格中显示的数据。所以......我有3行,其中propertyIds为firstNumber,secondNumber,第4行代表行的总和。所以,我从数据库中获得了一些数据。我需要手动“从键盘”到网格包含一些数据......

想象一下情况:

firstNumber在网格1中有数据,null,2 - 第4个单元格中的总和为3.我想在单元格中添加或更改数据。现在我添加第二个位置编号5.在网格中我现在有数字:1,5和2.我想在第四个单元格中立刻得到总和8。这是我的大问题。

我尝试将ValueChangeListener添加到网格中。

     container.addValueChangeListener(e -> {

     int sum = 0;

     for(int i = 1; i <= 3; i++)
     {
       Item item = container.getItem(i);
       sum += (Integer) item.getItemProperty("firstNumber").getValue();
     }

       item = container.getItem(4);
       item.getItemProperty("firstNumber").setValue(sum);

       grid.recalculateColumnWidths();
       grid.clearSortOrder();
       grid.refreshAllRows();

 });

所以我收到错误:

sep 15, 2017 4:16:21 PM com.vaadin.server.DefaultErrorHandler doDefault
SEVERE: 
com.vaadin.data.Buffered$SourceException
    at com.vaadin.ui.AbstractField.setValue(AbstractField.java:546)
    at com.vaadin.ui.AbstractField.setValue(AbstractField.java:468)
    at com.vaadin.ui.AbstractTextField.changeVariables(AbstractTextField.java:205)
    at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:616)
    at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:463)
    at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:406)
    at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:273)
    at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
    at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1422)
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:380)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689)
    at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1174)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1106)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
    at org.eclipse.jetty.server.Server.handle(Server.java:524)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
    at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
    at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.StackOverflowError
    at java.util.Hashtable.get(Hashtable.java:366)
    at com.vaadin.data.util.IndexedContainer$IndexedContainerProperty.setValue(IndexedContainer.java:848)
    at my.vaadin.app.MyUI.lambda$11(MyUI.java:3931)
    at com.vaadin.data.util.IndexedContainer.firePropertyValueChange(IndexedContainer.java:528)
    at com.vaadin.data.util.IndexedContainer.access$1000(IndexedContainer.java:63)
    at com.vaadin.data.util.IndexedContainer$IndexedContainerProperty.setValue(IndexedContainer.java:867)
    at my.vaadin.app.MyUI.lambda$11(MyUI.java:3931)

我的问题是,我可以拥有最后一行中的行总和。不在新专栏:)谢谢:)

enter image description here

2 个答案:

答案 0 :(得分:3)

您的Caused by: java.lang.StackOverflowError问题是因为您正在更改ValueChangeListener内的值,这会生成其他事件,并且最终会无限循环,因为 @Manuel Kollegger 我试图指出,所以需要采用不同的方法。

我想到的最简单的想法是拥有一个生成的列,您可以根据另一个来计算该值。但是,根据docs,Vaadin 7中没有直接的方法来定义生成的列,因此您必须使用GeneratedPropertyContainer包装容器:

  

网格没有生成列。相反,容器数据源可以围绕GeneratedPropertyContainer

此外,您可能希望将generate属性设置为只读,以防止用户手动编辑它。

以下示例根据您的描述显示了如何完成此操作。请注意,为了简洁起见,它并不完全是万无一失的(空值,无效值等),但它应该让你开始:

import com.vaadin.data.Item;
import com.vaadin.data.util.GeneratedPropertyContainer;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.data.util.PropertyValueGenerator;
import com.vaadin.ui.Grid;
import com.vaadin.ui.VerticalLayout;

import java.util.Random;

public class GridWithCalculatedColumn extends VerticalLayout {

    public GridWithCalculatedColumn() {
        // indexed container allowing the definition of custom properties
        IndexedContainer container = new IndexedContainer();
        container.addContainerProperty("firstNumber", Integer.class, 0);
        container.addContainerProperty("secondNumber", Integer.class, 0);

        // generated property container allowing the definition of generated properties
        GeneratedPropertyContainer wrappingContainer = new GeneratedPropertyContainer(container);
        wrappingContainer.addGeneratedProperty("sum", new PropertyValueGenerator<Integer>() {
            @Override
            public Integer getValue(Item item, Object itemId, Object propertyId) {
                // sum the other 2 columns
                // NOTE: for the sake of simplicity this does not handle invalid values such as "null"
                return (Integer) item.getItemProperty("firstNumber").getValue() + (Integer) item.getItemProperty("secondNumber").getValue();
            }

            @Override
            public Class<Integer> getType() {
                return Integer.class;
            }
        });

        // add some dummy data
        Random random = new Random();
        for (int i = 0; i < 5; i++) {
            Item item = wrappingContainer.addItem(i);
            item.getItemProperty("firstNumber").setValue(random.nextInt(10));
            item.getItemProperty("secondNumber").setValue(random.nextInt(10));
        }


        // basic grid setup
        Grid grid = new Grid();
        grid.setContainerDataSource(wrappingContainer);
        grid.setEditorEnabled(true);
        // disable editing of the "calculated value"
        grid.getColumn("sum").setEditable(false);
        addComponent(grid);
    }
}

结果:

vaadin 7 - grid generated property

答案 1 :(得分:0)

使用Vaadin 7.4.9在网格方面非常繁琐。

必须使用container.removeItem(item)删除项目。

另外,在Vaadin 7.7(添加refreshAllrefreshRow()的方法)中更容易刷新网格,在Vaadin 8中尤其容易(使用事件和数据提供者)。

在Vaadin 7中,你必须通过调用自动重绘网格的clearSortOrder来破解它。

当您从另一个线程(即不在ValueChangeListener中)更新UI时,将使用以下代码,但是您需要启用Vaadin-Push Addon,它是一个单独的依赖项。

getUI.access(() -> {
        List<SortOrder> sortOrders = new ArrayList<>();
        grid.getSortOrder().forEach(sortOrder -> sortOrders.add(sortOrder));
        grid.recalculateColumnWidths();
        grid.clearSortOrder();
        grid.setSortOrder(sortOrders);

        getUI().push();
    });

编辑:如果使用组合框的buttonClick或ValueChangeEvent进行删除,您可以执行以下操作:

component.addValueChangeListener(e -> {

         Item item = container.getItem(35);
         container.removeItem(item);    

         container.addItem(35);

         item.getItemProperty("Person5").setValue("SS");

         grid.recalculateColumnWidths();
         grid.clearSortOrder();
         grid.refreshAllRows();

     });

但是请注意,您的实现在容器上有一个ValueChangeListener,它调用container.removeItem(35)这将导致另一个触发另一个ValueChanged-Event,它将尝试再次删除项目编号35。您必须为ValueChangeListener使用另一个组件,否则您将遇到无限循环