CheckBoxTableViewer
继承了TableViewer
,二者以下简称viewer/查看器,看起来就是表格。
类似MVC模式。M即下文说的数据模型,是一个集合,比如
DataStore
;C可以认为是内容提供器,把数据模型以对象数组形式返回;V可以认为是标签提供器和显示用的组件,标签提供器需要把数据模型解析到viewer中的一个个单元格,集合内的每个元素都是一个对象,表格中的每一列对应对象的一个属性,对于DataObject
则需要按照key返回对应的value。
创建Table
//创建table
Table table = new Table(shell, SWT.CHECK|SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER|SWT.V_SCROLL|SWT.H_SCROLL);
table.setLayoutData(new GridData(GridData.FILL_BOTH));
table.setLinesVisible(true);
table.setHeaderVisible(true);
table.setBounds(97, 79, 373, 154);
从Table获取Viewer对象
//创建CheckboxTableViewer
final CheckboxTableViewer tableViewer = new CheckboxTableViewer(table);
为Table设计列名/表头
//准备数据模型DataStore
DataStore dataStore= DataStore.getInstance();
dataStore.put(0,"id",147);
dataStore.put(0,"name","NYF");
dataStore.put(0,"sex","男");
dataStore.put(0,"age",20);
dataStore.put(0,"createDate",new Date());
dataStore.put(1,"id",247);
dataStore.put(1,"name","Nnn");
dataStore.put(1,"sex","男");
dataStore.put(1,"age",20);
dataStore.put(1,"createDate",new Date());
//通过dataStore获取列名
String[] tableCols = dataStore.getColumnName();
//设计列
for(String colStr : tableCols) {
TableColumn tc = new TableColumn(table, SWT.LEFT); //靠左
tc.setText(colStr);
tc.setWidth(70);
}
设置内容提供器
//设置内容提供器
tableViewer.setContentProvider(new ContentProvider());
设置标签提供器
//设置标签提供器
tableViewer.setLabelProvider(new TableLabelProvider());
把数据集合(数据模型)交给Viewer
//把数据集合给tableView
tableViewer.setInput(dataStore);
内容提供器
实现IStructuredContentProvider
接口,getElements()
方法会把元素集合以数组的形式返回给Viewer。
import com.dareway.framework.util.DataStore;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;
import java.util.List;
public class ContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object inputElement) {
if (inputElement instanceof DataStore) {
return ((DataStore) inputElement).toArray();
} else {
return new Object[0];
}
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
标签提供器
实现ITableLabelProvider
接口,拿到元素集合后,Viewer利用标签提供器将每个元素翻译成对应的单元格(文字或图片)。日常使用表格基本都是文字,所以主要重写getColumnText()
方法。在这个方法中根据columnIndex返回一个String填充到viewer的一个单元格中。
import com.dareway.framework.exception.AppException;
import com.dareway.framework.util.DataObject;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import java.text.SimpleDateFormat;
public class TableLabelProvider implements ITableLabelProvider {
@Override
public Image getColumnImage(Object arg0, int arg1) {
return null;
}
@Override
public String getColumnText(Object element, int columnIndex) {
if (element instanceof DataObject) {
DataObject dataObject=(DataObject) element;
//columnNames和columnTypes是可以对应的
//Object[] columnNames = dataObject.keySet().toArray();
//String[] columnTypes=dataObject.getValueTypes();
if (columnIndex == 0) {
try {
return String.valueOf(dataObject.getInt("id"));
} catch (AppException e) {
e.printStackTrace();
}
} else if (columnIndex == 1) {
try {
return dataObject.getString("name");
} catch (AppException e) {
e.printStackTrace();
}
} else if (columnIndex == 2) {
try {
return dataObject.getString("sex");
} catch (AppException e) {
e.printStackTrace();
}
} else if (columnIndex == 3) {
try {
return String.valueOf(dataObject.getInt("age"));
} catch (AppException e) {
e.printStackTrace();
}
} else if (columnIndex == 4) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
return sdf.format(dataObject.getDate("createDate"));
} catch (AppException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
public void addListener(ILabelProviderListener iLabelProviderListener) {
}
@Override
public void dispose() {
}
@Override
public boolean isLabelProperty(Object o, String s) {
return false;
}
@Override
public void removeListener(ILabelProviderListener iLabelProviderListener) {
}
}
? 数据模型赋给viewer之后,有以下方法可更新表格的显示内容。
refresh()
方法刷新表格。直接修改数据模型,包括增删改。
调用Viewer的refresh()
方法刷新表格。
给数据模型添加增删改的监听器。
修改模型中的元素后会自动刷新Viewer。
TableViewer和数据模型(本例中的是DataStore对象)中都能够增加删除一条记录,区别在于Viewer中的方法只是在对显示界面的数据进行操作,并未改变数据模型中的数据;而直接在数据模型中增删数据需要调用Viewer的
refresh()
方法才能显示出增删的数据。
自定义CellModifier类,实现ICellModifier接口。
canModify()
方法直接返回true。
getValue()
方法不可为空,必须编写,否则抛异常,因为要获取每个单元格该显示的值。鼠标点击该单元格,此时调用一次显示旧数据,随后进入编辑状态,编辑完毕后鼠标离开该单元格,该方法再次调用以显示新数据。
在每次编辑完新的值之后,会进入modify()
方法为单元格设定新编辑的值,在该方法最后一定要调用update()
方法,否则光标离开时显示的还是旧数据。
注:编辑表格之后会同时修改数据模型。
import com.dareway.framework.exception.AppException;
import com.dareway.framework.util.DataObject;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.widgets.TableItem;
public class MyCellModifier implements ICellModifier {
private TableViewer tv;
public MyCellModifier(TableViewer tv) {
this.tv = tv;
}
@Override
public boolean canModify(Object o, String s) {
return true;
}
@Override
public Object getValue(Object element, String property) {
DataObject dataObject = (DataObject) element;
if (property.equals("name")) {
try {
return dataObject.getString("name");
} catch (AppException e) {
e.printStackTrace();
}
} else if (property.equals("sex")) {
try {
return dataObject.getString("sex");
} catch (AppException e) {
e.printStackTrace();
}
} else if (property.equals("age")) {
try {
return String.valueOf(dataObject.getInt("age"));
} catch (AppException e) {
e.printStackTrace();
}
}
throw new RuntimeException("error column name : " + property);
}
@Override
public void modify(Object element, String property, Object value) {
TableItem item=(TableItem)element;
DataObject dataObject=(DataObject)item.getData();
if(property.equals("name")){
String newName = (String)value;
if(newName.equals("")){
return ;
}
try {
dataObject.put("name",newName);
} catch (AppException e) {
e.printStackTrace();
}
}else if (property.equals("sex")){
String newSex = (String)value;
if(newSex.equals("")){
return ;
}
try {
dataObject.put("sex",newSex);
} catch (AppException e) {
e.printStackTrace();
}
}else if(property.equals("age")){
String newValue = (String)value;
if(newValue.equals("")){
return ;
}
Integer newAge = new Integer(newValue);
try {
dataObject.put("age",newAge);
} catch (AppException e) {
e.printStackTrace();
}
}
tv.update(dataObject, null);
}
}
为Viewer设置Modifier
//设置编辑器
tableViewer.setColumnProperties(tableCols);
CellEditor[] cellEditor = new CellEditor[5];
cellEditor[0] = null;//不编辑
cellEditor[1] = new TextCellEditor(tableViewer.getTable());//以下三个可手动编辑
cellEditor[2] = new TextCellEditor(tableViewer.getTable());
cellEditor[3] = new TextCellEditor(tableViewer.getTable());
cellEditor[4] = null;//日期暂时不编辑
tableViewer.setCellEditors(cellEditor);
ICellModifier modifier = new MyCellModifier(tableViewer);
tableViewer.setCellModifier(modifier);
注释:日期类型组件暂时需要进一步定制
增加与删除目前计划方案是:
添加按钮,为该按钮添加监听器,触发该监听器之后,在表格上编辑新行或者在数据模型上增减数据,然后刷新viewer。(操作和贡献好像比单纯的监听器更好用?)
addDropSupport目前用法不明
? 直接按照排序标准给数据模型排序,然后刷新viewer,如果DS的排序够用,这种方法可能方便。
自定义Sorter,继承ViewerSorter
,实现compare()
方法。
为每一列添加selecte监听器,之后每次点击该列的表头都会按照该列排序。此方式相对繁琐。
自定义过滤器类,继承ViewerFilter
,实现select()
方法,在该方法中定义自己的过滤标准。
import com.dareway.framework.exception.AppException;
import com.dareway.framework.util.DataObject;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
public class MyFilter extends ViewerFilter {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
DataObject dataObject = (DataObject) element;
boolean result=false;
try {
result=dataObject.getString("name").startsWith("Nn");
} catch (AppException e) {
e.printStackTrace();
}
return result;
}
}
添加/移除过滤器
//添加过滤器,添加即生效
MyFilter myFilter=new MyFilter();
tableViewer.addFilter(myFilter);
//移除过滤器,移除即失效
tableViewer.removeFilter(myFilter);
? DS继承了ArrayList
,也是数据集合,所以可以直接把它交给tableView,具体显示则需要设计内容提供器和标签提供器。
如何根据查询结果显示列名?
获得DS之前无从得知每一列的名字。可通过DS获取列名返回一个数组,在表初始化设计列名时可以利用该数组生成列名。
提升标签提供器的解析能力:需要设计根据columnIndex返回对应的字符串。详情见基本使用的注释部分中标签提供器的getColumnText()
方法,该方法对一个DS进行了解析。
方法1:先获取viewer的元素,一个元素就是一行,也就是一个DataObject
,再调用DS的addRow()
方法。
DataStore getDS=DataStore.getInstance();
int rows=table.getItemCount();
for (int i = 0; i < rows; i++) {
getDS.addRow((DataObject) tableViewer.getElementAt(i));
}
方法2:直接获取数据模型。
DataStore dataStore= (DataStore) tableViewer.getInput();
生成Menu
对象
Menu menu = new Menu(shell,SWT.POP_UP);
添加MenuItem
,并为该项设置属性以及监听器。
MenuItem ascMenuItem=new MenuItem(menu,SWT.PUSH);
ascMenuItem.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent selectionEvent) {
try {
dataStore.sort("age");
tableViewer.refresh();
} catch (AppException e) {
e.printStackTrace();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent selectionEvent) {
}
});
ascMenuItem.setText("age升序");
为viewer添加右键菜单
table.setMenu(menu);
? 直接使用CheckBoxTableViewer,利用其自带的selectionAll等相关方法。
? 添加快捷键(还没学)
需要学习鼠标事件。效果如下图。
CellEditor: https://www.cnblogs.com/wayne_wang/archive/2010/01/25/1655742.html
Viewer: https://www.cnblogs.com/xing901022/p/4104409.html
? http://www.blogjava.net/dreamstone/category/24602.html?Show=All
日期时间: https://www.cnblogs.com/huqingyu/archive/2008/04/16/1156428.html
? https://blog.csdn.net/zengjz888/article/details/84215227
原文:https://www.cnblogs.com/nyfblog/p/14180124.html