建立了一个自己的通用的表格:
a)Comp为Table的父亲,在这个上面建table,class是要显示的实体类,ignoreList中,如果和class的filed名字一样就不建立这个列。
b)列隐藏伸展
c)显示默认就对应类的Field的toString
d)上下自动滚动。
e)Ctrl+鼠标滚动列。
f)当点击Table的其他位置的时候,就是没有Item的位置的时候,取消所以的选择。
g)列的Properties就是列的Class的Field。(还不知道Properties有用否)
代码:
public class MyTable {
private static String RESTORE_COL_WIDTH = "restoredWidth";
private TableViewer v;
private Table t;
private MenuManager tableContextMenu;
private List<String> ignoreList;
private List<String> propertis;
private Map<String,TableViewerColumn> columMap = new HashMap<String,TableViewerColumn>();
/*
* for auto scroll
*/
private Runnable Heartbeat;
private boolean Tracking;
private int ScrollSpeed = 400;
public MyTable(Composite comp, Class<?> clazz) {
createTable(comp,clazz);
}
public MyTable(Composite comp, Class<?> clazz, List<String> ignoreList) {
this.ignoreList = ignoreList;
createTable(comp,clazz);
}
private void createTable(Composite comp, Class<?> clazz) {
v = new TableViewer(comp, SWT.FULL_SELECTION | SWT.MULTI);
t = v.getTable();
t.setLinesVisible(true);
t.setHeaderVisible(true);
v.setContentProvider(new MyContentProvider());
getPropertis(clazz);
v.setColumnProperties(propertis.toArray(new String[0]));
createColumn();
setTableMenu();
addVerticalAutoScroll();
addCtrlScroll();
addDesWhenNull();
v.setInput(new TableData());
}
private void addDesWhenNull() {
/*
* deselectAll when mouse click a space in table.
*/
t.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
if(t.getItem(new Point(e.x,e.y)) == null ) {
t.deselectAll();
}
}
});
}
private void addCtrlScroll() {
t.addMouseWheelListener(new MouseWheelListener() {
public void mouseScrolled(MouseEvent e) {
if (e.stateMask == SWT.CTRL) {
/*
* using getClientArea().width, hBar.getSelection(), e.count to calc
* which column to show.
* t.showColumn();
*/
ScrollBar hBar = t.getHorizontalBar();
if(hBar != null) {
TableColumn col = getShowColumn(hBar,e.count);
if(col != null)
t.showColumn(col);
}
}
}
private TableColumn getShowColumn(ScrollBar hBar, int count) {
TableColumn col;
TableColumn[] cols = t.getColumns();
int totalWidth = t.getBounds().width;
int hBarLeft = hBar.getSelection();
int hBarRight = hBar.getMaximum() - hBar.getThumb() - hBar.getSelection();
if(count > 0) {
int colsWidth = 0 - hBarRight;
for(int i=cols.length-1; i > -1; i--) {
col = cols[i];
colsWidth += col.getWidth();
if(colsWidth > totalWidth)
return col;
}
} else {
int colsWidth = 0 - hBarLeft;
for(int i=0; i < cols.length; i++) {
col = cols[i];
colsWidth += col.getWidth();
if(colsWidth > totalWidth)
return col;
}
}
return null;
}
});
}
private void addVerticalAutoScroll() {
/*
* swt.snippets.Snippet221
*/
Heartbeat = new Runnable() {
public void run() {
if(!Tracking || t.isDisposed()) return;
Point cursor = Display.getCurrent().getCursorLocation();
cursor = Display.getCurrent().map(null, t, cursor);
Scroll(t, cursor);
Display.getCurrent().timerExec(ScrollSpeed, Heartbeat);
}
private void Scroll(Table t, Point cursor) {
TableItem item = t.getItem(cursor);
if (item == null) return;
int index = t.indexOf(item);
if(index == 0 || index == t.getItemCount()-1)
return;
Rectangle area = t.getClientArea();
int headerHeight = t.getHeaderHeight();
int itemHeight= t.getItemHeight();
if (cursor.y < area.y + headerHeight + 2 * itemHeight) {
// mouse in the first or second item.
index --;
}
if (cursor.y > area.y + area.height - 2 * itemHeight) {
// mouse in the last first or second item.
index ++;
}
if(index>-1 && index<t.getItemCount())
t.showItem(t.getItem(index));
}
};
Listener listener = new Listener() {
public void handleEvent(Event event) {
switch (event.type) {
case SWT.MouseEnter:
Tracking = true;
Display.getCurrent().timerExec(0, Heartbeat);
break;
case SWT.MouseExit:
Tracking = false;
break;
}
}
};
t.addListener(SWT.MouseEnter, listener);
t.addListener(SWT.MouseExit, listener);
}
private void setTableMenu() {
final MenuManager headerMenu = new MenuManager();
addAction2HeaderMenu(headerMenu);
t.addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
Point pt = Display.getCurrent().map(null, t, new Point(event.x, event.y));
Rectangle clientArea = t.getClientArea();
boolean header = clientArea.y <= pt.y && pt.y < (clientArea.y + t.getHeaderHeight());
if(header) {
t.setMenu(headerMenu.createContextMenu(t));
} else {
if(tableContextMenu != null)
t.setMenu(tableContextMenu.createContextMenu(t));
}
}
});
}
private void addAction2HeaderMenu(MenuManager menu) {
Action action;
for(int i = 0; i < t.getColumnCount(); i++ ) {
final TableColumn column = t.getColumn(i);
action = new Action(t.getColumn(i).getText(),SWT.CHECK) {
public void run() {
if(!isChecked()) {
ShrinkThread t = new ShrinkThread(column.getWidth(),column);
t.run();
} else {
ExpandThread t = new ExpandThread(((Integer)column.getData(RESTORE_COL_WIDTH)).intValue(),column);
t.run();
}
}
};
action.setChecked(true);
menu.add(action);
}
}
private void createColumn() {
for(String property : propertis) {
TableViewerColumn column = new TableViewerColumn(v, SWT.NONE);
column.getColumn().setWidth(200);
column.getColumn().setText(property);
column.getColumn().setMoveable(true);
column.setLabelProvider(new MyColumnLabelProvider(property));
columMap.put(property, column);
}
}
public List<String> getPropertis() {
return propertis;
}
private void getPropertis(Class<?> clazz) {
propertis = new ArrayList<String>();
String name;
for(Field f : clazz.getDeclaredFields()) {
name = f.getName();
if(!ignoreList.contains(name))
propertis.add(f.getName());
}
}
public void add(Object o) {
((TableData)v.getInput()).add(o);
}
public void remove(Object o) {
((TableData)v.getInput()).remove(o);
}
public void removeAll() {
v.setInput(new TableData());
}
public void setColumnWidth(int width) {
for(TableColumn col : v.getTable().getColumns())
col.setWidth(width);
}
public void setColumnWidth(int[] widths) {
int min = Math.min(widths.length, t.getColumnCount());
for(int i=0; i<min; i++) {
t.getColumn(i).setWidth(widths[i]);
}
}
public void setColumnName(String[] names) {
int min = Math.min(names.length, t.getColumnCount());
for(int i=0; i<min; i++) {
t.getColumn(i).setText(names[i]);
}
}
public TableViewerColumn getTableViewerColumn(String property) {
return columMap.get(property);
}
public void setColumnLabelProvider(String property,ColumnLabelProvider columnLabelProvider) {
columMap.get(property).setLabelProvider(columnLabelProvider);
}
public void setContextMenu(MenuManager menu) {
tableContextMenu = menu;
}
public TableViewer getTableViewer() {
return v;
}
/**
* column shrink
*/
private class ShrinkThread extends Thread {
private int width = 0;
private TableColumn column;
public ShrinkThread(int width, TableColumn column) {
super();
this.width = width;
this.column = column;
}
public void run() {
column.getDisplay().syncExec(new Runnable() {
public void run() {
column.setData(RESTORE_COL_WIDTH, new Integer(width));
}
});
for(int i = width; i >= 0; i--) {
final int index = i;
column.getDisplay().syncExec(new Runnable() {
public void run() {
column.setWidth(index);
}
});
}
column.setResizable(false);
}
};
/**
* column Expand
*/
private class ExpandThread extends Thread {
private int width = 0;
private TableColumn column;
public ExpandThread(int width, TableColumn column) {
super();
this.width = width;
this.column = column;
}
public void run() {
for(int i = 0; i <= width; i++) {
final int index = i;
column.getDisplay().syncExec(new Runnable() {
public void run() {
column.setWidth(index);
}
});
}
column.setResizable(true);
}
}
private class MyContentProvider implements IStructuredContentProvider ,PropertyChangeListener{
private TableViewer viewer;
public Object[] getElements(Object inputElement) {
if(inputElement instanceof TableData)
return ((TableData)inputElement).elements();
return null;
}
public void dispose() {}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
this.viewer = (TableViewer) viewer;
if (oldInput instanceof TableData)
((TableData) oldInput).removePropertyChangeListener(this);
if (newInput instanceof TableData) {
((TableData) newInput).addPropertyChangeListener(this);
}
}
public void propertyChange(PropertyChangeEvent event) {
if (TableData.ADD_ELEMENT.equals(event.getPropertyName()))
viewer.add(event.getNewValue());
if (TableData.REMOVE_ELEMENT.equals(event.getPropertyName()))
viewer.remove(event.getNewValue());
}
}
private class MyColumnLabelProvider extends ColumnLabelProvider {
private String FieldName;
public MyColumnLabelProvider(String columnText) {
super();
this.FieldName = columnText;
}
public String getText(Object element) {
Object o = getClassFieldContent(element, FieldName);
return o == null ?"":o.toString();
}
private Object getClassFieldContent(Object obj, String fieldName) {
Object o = null;
for(Field f : obj.getClass().getDeclaredFields()) {
if(f.getName().equals(fieldName)) {
f.setAccessible(true);
try {
o = f.get(obj);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return o;
}
}
}
abstract class ColumnViewerSorter extends ViewerComparator {
public static final int ASC = 1;
public static final int NONE = 0;
public static final int DESC = -1;
private int direction = 0;
private TableViewerColumn column;
private ColumnViewer viewer;
private String property;
public ColumnViewerSorter(ColumnViewer viewer, TableViewerColumn column, String property) {
this.column = column;
this.viewer = viewer;
this.property = property;
this.column.getColumn().addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if( ColumnViewerSorter.this.viewer.getComparator() != null ) {
if( ColumnViewerSorter.this.viewer.getComparator() == ColumnViewerSorter.this ) {
int tdirection = ColumnViewerSorter.this.direction;
if( tdirection == ASC ) {
setSorter(ColumnViewerSorter.this, DESC);
} else if( tdirection == DESC ) {
setSorter(ColumnViewerSorter.this, NONE);
}
} else {
setSorter(ColumnViewerSorter.this, ASC);
}
} else {
setSorter(ColumnViewerSorter.this, ASC);
}
}
});
}
public void setSorter(ColumnViewerSorter sorter, int direction) {
if( direction == NONE ) {
column.getColumn().getParent().setSortColumn(null);
column.getColumn().getParent().setSortDirection(SWT.NONE);
viewer.setComparator(null);
} else {
column.getColumn().getParent().setSortColumn(column.getColumn());
sorter.direction = direction;
if( direction == ASC ) {
column.getColumn().getParent().setSortDirection(SWT.DOWN);
} else {
column.getColumn().getParent().setSortDirection(SWT.UP);
}
if( viewer.getComparator() == sorter ) {
viewer.refresh();
} else {
viewer.setComparator(sorter);
}
}
}
public int compare(Viewer viewer, Object e1, Object e2) {
return direction * doCompare(e1, e2, property);
}
protected abstract int doCompare(Object e1, Object e2, String property);
}
表格数据类代码:
public class TableData {
public static final String ADD_ELEMENT = "add Element";
public static final String REMOVE_ELEMENT = "remove Element";
private PropertyChangeSupport delegate;
private Vector<Object> content;
public TableData() {
content = new Vector<Object>();
delegate = new PropertyChangeSupport(this);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
delegate.addPropertyChangeListener(listener);
}
public void firePropertyChange(PropertyChangeEvent event) {
delegate.firePropertyChange(event);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
delegate.removePropertyChangeListener(listener);
}
public void add(Object element) {
if(content.contains(element))
return;
if(content.add(element))
firePropertyChange(new PropertyChangeEvent(this, ADD_ELEMENT, null, element));
}
public void remove(Object element) {
if (content.remove(element))
firePropertyChange(new PropertyChangeEvent(this, REMOVE_ELEMENT, null, element));
}
public Object[] elements() {
return content.toArray();
}
public void printInfo() {
for(Object o : content)
System.out.println(o);
}
}
测试代码:
public class MyTableTst {
private static Shell shell;
public MyTableTst(Shell shell) {
MyTable table = new MyTable(shell,MyModel.class,Arrays.asList(new String[]{"serialVersionUID","xx_dialog2"}));
/*
* add and remove object
*/
Object o = new MyModel(2);
table.add(o);
table.add(new MyModel(4));
table.add(new MyModel(55));
for(int i=0; i<30; i++)
table.add(new MyModel(4));
o = new MyModel(3);
table.add(o);
table.remove(o);
/*
* set column width and text
*/
table.setColumnWidth(300);
// table.setColumnWidth(new int[]{100,100,150,160,100});
table.setColumnName(new String[]{"text","id","boolean","b","e"});
/*
* set context menu
*/
table.setContextMenu(CreateContextMenu(table.getTableViewer()));
/*
* reset column label provider
*/
for(String property : table.getPropertis()) {
table.setColumnLabelProvider(property,new ChangedColumnLabelProvider(property));
}
table.getTableViewer().refresh();
/*
* set sort to the table
*/
for(String property : table.getPropertis()) {
new ColumnViewerSorter(table.getTableViewer(),table.getTableViewerColumn(property),property) {
protected int doCompare(Object e1, Object e2, String property) {
if(e1 instanceof MyModel)
return ((MyModel)e1).doCompare((MyModel)e2, property);
return 0;
}
};
}
/*
* add filter
*/
table.getTableViewer().addFilter(new ViewerFilter() {
public boolean select(Viewer viewer, Object parentElement, Object element) {
/*
* viewer - TableViewer
* parentElement - TableData
* element - MyModel
*/
if(element instanceof MyModel)
return ((MyModel)element).filter();
return true;
}
});
/*
* add EditingSupport
*/
TableViewerColumn column = table.getTableViewerColumn("xx_Text_String");
column.setEditingSupport(new AbstractEditingSupport(table.getTableViewer()) {
protected Object getValue(Object element) {
return ((MyModel) element).xx_Text_String;
}
protected void doSetValue(Object element, Object value) {
((MyModel) element).xx_Text_String = value.toString();
}
});
}
private MenuManager CreateContextMenu(TableViewer v) {
MenuManager menu = new MenuManager();
menu.add(CeActionFactory.getDelAction(v));
return menu;
}
public static void main(String[] args) {
Display display = new Display ();
shell = new Shell(display);
shell.setLayout(new FillLayout());
new MyTableTst(shell);
shell.open ();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
protected abstract class AbstractEditingSupport extends EditingSupport {
private TextCellEditor editor;
public AbstractEditingSupport(TableViewer viewer) {
super(viewer);
this.editor = new TextCellEditor(viewer.getTable());
}
protected boolean canEdit(Object element) {
return true;
}
protected CellEditor getCellEditor(Object element) {
return editor;
}
protected void setValue(Object element, Object value) {
doSetValue(element, value);
getViewer().update(element, null);
}
protected abstract void doSetValue(Object element, Object value);
}
}
class MyModel {
protected int xx_Text_int = 1;
protected long longT = 1111111111L;
protected boolean xx_Boolean = true;
protected boolean Ignorable_Boolean = true;
public String xx_Text_String = "a string";
protected List<String> list_dialog1 = Arrays.asList(new String[]{"list1","list2"}); //端口或者引脚 Clock sources ports or pins
protected String xx_dialog2 = "dialog2";
protected String xx_Combo_list1 = "";
public MyModel() {}
public MyModel(int i) {
xx_Text_int = i;
}
/*
* false - filter.
* true - display.
*/
public boolean filter() {
if(xx_Text_int == 5)
return false;
return true;
}
public int doCompare(MyModel model, String field) {
if(field.equals("xx_Text_int"))
return ((Integer)this.xx_Text_int).compareTo((Integer)model.xx_Text_int);
if(field.equals("longT"))
return ((Long)this.longT).compareTo((Long)model.longT);
if(field.equals("xx_Boolean"))
return ((Boolean)this.xx_Boolean).compareTo((Boolean)model.xx_Boolean);
if(field.equals("Ignorable_Boolean"))
return ((Boolean)this.Ignorable_Boolean).compareTo((Boolean)model.Ignorable_Boolean);
if(field.equals("xx_Text_String"))
return this.xx_Text_String.compareTo(model.xx_Text_String);
if(field.equals("list_dialog1"))
return ((Integer)this.list_dialog1.size()).compareTo((Integer)model.list_dialog1.size());
if(field.equals("xx_dialog2"))
return this.xx_dialog2.compareTo(model.xx_dialog2);
if(field.equals("xx_Combo_list1"))
return this.xx_Combo_list1.compareTo(model.xx_Combo_list1);
return 0;
}
}
class ChangedColumnLabelProvider extends ColumnLabelProvider {
private String columnText;
public ChangedColumnLabelProvider(String columnText) {
super();
this.columnText = columnText;
}
public Image getImage(Object element) {
return Display.getCurrent().getSystemImage(SWT.ICON_WARNING);
}
public Font getFont(Object element) {
return JFaceResources.getFont(JFaceResources.HEADER_FONT);
}
public Color getBackground(Object element) {
return Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
}
public Color getForeground(Object element) {
return Display.getCurrent().getSystemColor(SWT.COLOR_GREEN);
}
public String getText(Object element) {
Object o = getClassFieldContent(element, columnText);
return o == null ?"":o.toString();
}
private Object getClassFieldContent(Object obj, String fieldName) {
Object o = null;
for(Field f : obj.getClass().getDeclaredFields()) {
if(f.getName().equals(fieldName)) {
f.setAccessible(true);
try {
o = f.get(obj);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return o;
}
public void dispose(ColumnViewer viewer, ViewerColumn column) {
super.dispose(viewer, column);
}
}
class CeActionFactory {
public static Action getDelAction(final TableViewer v) {
Action action = new Action("Del") {
public void run() {
v.getTable().remove(v.getTable().getSelectionIndices());
}
};
action.setImageDescriptor(ImageDescriptor.createFromImage(
Display.getCurrent().getSystemImage(SWT.ICON_ERROR)));
return action;
}
}
测试了功能:
a)可设置列的默认宽,可设置每一列的宽。可改变列的名字。
b)可设置Table上下文的菜单。
c)可以添加,删除,删除所有。
d)可以接受更改columnLabelProvide。
e)编辑,是不是用editorsupport更方便,看看。
f)Sort扩展。
g)Filter。