在Vaadin 7.0 中,当使用BeanContainer在Table中显示JavaBean数据时,用新数据刷新 Table 的正确方法是什么?
3 回答
该表通过侦听器监视表项的属性。如果您通过表的 Item 实例更改项目的属性,则表将被通知和更新:例如
container.getItem(beanInstance).getItemProperty("propertyName").setValue("newValue");
但是,如果 bean在项目实例之外发生了更改,您需要告诉表刷新。最简单的方法(使用股票 BeanContainer)是简单地删除然后添加项目。
或者 - 我建议,最好 - 您可以创建 BeanItemContainer 的扩展来触发 ItemSetChange 事件,这将导致表刷新。
public class RefreshableBeanItemContainer<BEANTYPE> extends BeanItemContainer<BEANTYPE> {
public RefreshableBeanItemContainer(Collection<? extends BEANTYPE> collection) throws IllegalArgumentException {
super(collection);
}
public RefreshableBeanItemContainer(Class<? super BEANTYPE> type) throws IllegalArgumentException {
super(type);
}
public RefreshableBeanItemContainer(Class<? super BEANTYPE> type, Collection<? extends BEANTYPE> collection) throws IllegalArgumentException {
super(type, collection);
}
public void refreshItems(){
fireItemSetChange();
}
}
似乎刷新 JavaBean 数据的一种方法是将表的容器替换为另一个容器。我注意到的一个副作用是某些表格的设置可能会被重置,例如折叠的列不再被折叠。
另一种方法似乎是在替换包含的 Bean 时保留容器。
我不确定这两种方法是否都被认为是正确的。而且我不确定这两种方法的权衡可能是什么。
这是一个带有一对表格和一个按钮的示例应用程序。当用户单击按钮时,两个表都会获得新数据。一个 Table 获得一个新的 BeanContainer。另一个表保留它的 BeanContainer,但会加载新的 bean。
这个应用程序中只有两个类:
- 主应用程序类。
- 用于存储数据的 JavaBean 类。
package com.example.replacebeansorcontainer;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.vaadin.data.util.BeanContainer;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
/**
* Main UI class.
*
* ReplaceBeansOrContainerUI.java
*
* @author Basil Bourque
*
* Copyright © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
*
*/
@SuppressWarnings( "serial" )
public class ReplaceBeansOrContainerUI extends UI {
Table tableThatGetsFreshContainer;
Table tableThatGetsFreshBeans;
@Override
protected void init( VaadinRequest request ) {
// Create widgets: table on the left, button, table on the right.
this.tableThatGetsFreshContainer = new Table( "Table That Gets Fresh Container", this.makeBeanContainer() );
this.tweakTable( this.tableThatGetsFreshContainer );
this.tableThatGetsFreshBeans = new Table( "Table That Gets Fresh Beans", this.makeBeanContainer() );
this.tweakTable( this.tableThatGetsFreshBeans );
Button reloadButton = new Button( "Reload Data" );
reloadButton.addClickListener( new Button.ClickListener() {
@Override
public void buttonClick( ClickEvent event ) {
// Reload data in both tables when user clicks this button.
System.out.println( "User clicked 'Reload Data' button. Replacing container (left) & beans (right)." + new java.util.Date() );
// One table gets a new Container.
ReplaceBeansOrContainerUI.this.tableThatGetsFreshContainer.setContainerDataSource( ReplaceBeansOrContainerUI.this.makeBeanContainer() );
// The other table keeps its Container, but the Container's beans are replaced.
ReplaceBeansOrContainerUI.this.tableThatGetsFreshBeans.getContainerDataSource().removeAllItems();
// Cast the Container to BeanContainer to utilize the 'addAll' method.
@SuppressWarnings( "unchecked" )
BeanContainer<UUID, MomentBean> beanContainer = (BeanContainer<UUID, MomentBean>)ReplaceBeansOrContainerUI.this.tableThatGetsFreshBeans.getContainerDataSource();
beanContainer.addAll( ReplaceBeansOrContainerUI.this.makeListOfBeans() );
}
} );
// Compose Layout.
final HorizontalLayout layout = new HorizontalLayout();
layout.setMargin( true );
layout.setSpacing( true );
layout.addComponent( this.tableThatGetsFreshContainer ); // Table on the left.
layout.addComponent( reloadButton );
layout.addComponent( this.tableThatGetsFreshBeans ); // Table on the right.
// Compose UI.
this.setContent( layout );
}
private void tweakTable( Table table ) {
table.setSelectable( true );
}
private List<MomentBean> makeListOfBeans() {
List<MomentBean> beans = new ArrayList<MomentBean>();
for ( int i = 0; i < 20; i++ ) {
beans.add( new MomentBean() );
}
return beans;
}
private BeanContainer<UUID, MomentBean> makeBeanContainer() {
// Instantiate empty container, with columns defined by my class’ JavaBean fields.
BeanContainer<UUID, MomentBean> container = new BeanContainer<UUID, MomentBean>( MomentBean.class );
try {
// Indicate which field in Bean serves as the unique identifier.
container.setBeanIdProperty( MomentBean.class.getDeclaredField( "uuid" ).getName() );
container.addAll( this.makeListOfBeans() ); // Add entire Collection of beans to container.
} catch ( NoSuchFieldException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch ( SecurityException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return container;
}
}
JavaBean 类...</p>
/**
*
*/
package com.example.replacebeansorcontainer;
import java.text.SimpleDateFormat;
import java.util.UUID;
/**
* MomentBean.java
*
* @author Basil Bourque
*
* Copyright © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
*
*/
public class MomentBean {
// Bean fields.
private final String clockTime;
private final long nanoTime;
private final UUID uuid;
// Other member fields.
private final SimpleDateFormat timeOnlyFormat = new SimpleDateFormat( "HH:mm:ss" );
/**
*
*/
public MomentBean() {
this.clockTime = this.timeOnlyFormat.format( new java.util.Date() );
this.nanoTime = System.nanoTime();
this.uuid = UUID.randomUUID();
}
/**
* @return the clockTime
*/
public String getClockTime() {
return this.clockTime;
}
/**
* @return the nanoTime
*/
public long getNanoTime() {
return this.nanoTime;
}
/**
* @return the uuid
*/
public UUID getUuid() {
return this.uuid;
}
}
似乎解决方案就像打电话一样简单refreshRowCache()
——至少对我来说是这样!