问题
I need to delete data from the grid (container) and then i need refresh the rows. How I can do it?
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");
Now I try to change cell only without delete item. My code is
container.addValueChangeListener(e -> {
Item item = container.getItem(35);
item.getItemProperty("Person5").setValue("SS");
grid.recalculateColumnWidths();
grid.clearSortOrder();
grid.refreshAllRows();
});
but the I have error too ... :(
Info for Morfic:
I need change data displayed in the grid cell. So ... I have e.g 3 rows with propertyIds firstNumber and secondNumber, the 4th row represent the sum of the rows. So, I have some data whitch I get from the database. And I need include some data manually "from keyboard" to the grid ...
Imagine the situation:
firstNumber have data in grid 1,null,2 - the sum in the 4th cell is 3. I want add or change data in the cell. Now I add at the second position number 5. In grid I have now numbers: 1,5 and 2. I want in no time have the sum 8 in the 4th cell. This is my big problem.
I tried add ValueChangeListener to the grid.
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();
});
So I get the error:
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)
My question is, that i can have the sum of the rows in the last row. Not in the new column :) Thanks :)
回答1:
Your Caused by: java.lang.StackOverflowError
problem is because you're changing values inside a ValueChangeListener
, which generates other events, and you end up in an endless loop, as @Manuel Kollegger was trying to point out, so a different approach is required.
The simplest idea which came to mind, is to have a generated column, for which you calculate the value based on the other 2. However, as per the docs, there's no direct way in Vaadin 7 to define a generated column, so you have to wrap your container with a GeneratedPropertyContainer
:
Grid has no generated columns. Instead, the container data source can be wrapped around a
GeneratedPropertyContainer
.
Also, you may wish to make the generate property read-only, to prevent the user from manually editing it.
The example below, based on your description, shows how this is done. Please note that for the sake of brevity, it's not entirely fool-proof (nulls, invalid values, etc), but it should get you started:
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);
}
}
Result:
回答2:
Using Vaadin 7.4.9 is very tedious when it comes to Grids.
Removing items has to be done using container.removeItem(item)
.
Additionally refreshing a Grid is easy in Vaadin 7.7 (method addition of refreshAll
and refreshRow()
) and especially easy in Vaadin 8 (using events and a Dataprovider).
In Vaadin 7 you will have to hack it a bit by calling clearSortOrder
which automatically redraws the grid.
The following code is used when you update the UI from another Thread (i.e. not in a ValueChangeListener) however you need to enable the Vaadin-Push Addon which is a separate dependency.
getUI.access(() -> {
List<SortOrder> sortOrders = new ArrayList<>();
grid.getSortOrder().forEach(sortOrder -> sortOrders.add(sortOrder));
grid.recalculateColumnWidths();
grid.clearSortOrder();
grid.setSortOrder(sortOrders);
getUI().push();
});
Edit: If you do the deletion with a buttonClick or ValueChangeEvent of a combobox you can simply do:
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();
});
However be careful, your implementation has a ValueChangeListener on the container which calls container.removeItem(35)
this will result in another trigger another ValueChanged-Event which will try to remove item number 35 again. You have to use another component for the ValueChangeListener otherwise you run into an endless cycle
来源:https://stackoverflow.com/questions/46078096/using-vaadin-7-4-9-how-to-delete-data-from-the-grid