最近在项目开发中需要对树(Tree)的层次结构进行调整,由于SWT是基于操作系统的事件模型的一种开发控件,所以想到利用鼠标的拖放功能对树的节点进行移动,即直观也提高了客户体验。
SWT的拖放功能的实现主要使用了DragSource、DropTarget这两个类,开发人员只需要实现其事件的接口,既可以对控件上的文本、HTML、RTF及附件进行拖放操作,即把一个控件上的文本、HTML、RTF及附件拖放到另一个控件。
Tree是由TreeItem控件组成,所以移动树节点就相当于移动TreeItem,这里并非真的移动控件,而是把源控件的信息(文本、HTML、RTF及附件)通过事件传递到目标控件,目标控件也是新创建的,如果不是复制而只是移动,则要把源控件销毁掉。
例子实现思路及源代码:本例子为左边是目标树,右边是用TabFolder实现了几棵源树,同时目标树本身也是源树,即实现多个源对单个目标进行操作。实现过程把几个源树放到了一个Tree[ ]集合里,用于分清源树到底是哪一棵,才能得到在源树上的选择的节点。本例的主要功能是:实现把其他源树的节点移动到某一个目标树上,同时实现目标树上的节点自由替换位置。
代码:
public
class
SetSubSWT
extends
Dialog
...
{
protected Tree subtree;
protected Tree preTree;// 单位
protected Tree roomTree;// 科室
protected Table unitTable;// 科室
protected Display display;
protected Shell shell;
protected Tree tree;
protected List newList = new ArrayList();
protected List modifyList = new ArrayList();
protected List deleteList = new ArrayList();
protected Map map = new HashMap();
protected Map mapSave = new HashMap();
protected Object result;
protected SashForm mainSashForm;
protected TextTransfer textTransfer;
protected FileTransfer fileTransfer;
protected Tree[] eachTrees;
// protected TreeItem[] dragSourceItem;
protected int index;
protected Map dataMap;// 缓存
protected List typeList;// 缓存
protected Map relMap;// 缓存
/** *//**
* Create the dialog
*
* @param parent
* @param style
*/
public SetSubSWT(Shell parent, Tree subtree, Map dataMap, List typeList,
Map relMap, int style) ...{
super(parent, style);
this.subtree = subtree;
this.dataMap = dataMap;
this.typeList = typeList;
this.relMap = relMap;
}
// /**
// * Create the dialog
// * @param parent
// */
// public SetSubSWT(Shell parent) {
// this(parent, SWT.NONE);
// }
// /**
// * Launch the application
// *
// * @param args
// */
// public static void main(String[] args) {
// try {
// System.out.println("args[0]==" + args[0]);
// SWTDataViewUtil.httpUrl = args[0] + "/subactionswt.do?action=";
// SetSubSWT window = new SetSubSWT();
// window.open();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
/** *//**
* Open the window
*/
public Object open() ...{
display = getParent().getDisplay();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) ...{
if (!display.readAndDispatch())
display.sleep();
}
return result;
}
/** *//**
* Create contents of the window
*/
protected void createContents() ...{
shell = new Shell();
shell.setLayout(new FillLayout());
shell.setText("会计科目设置");
/**//*
* Transfer是一个可以提供数据在Java representation与platform specific
* representation 之间交互的抽象类.下面是几个format: TextTransfer String "hello
* world" RTFTransfer String "{/rtf1/b/i hello world}" FileTransfer
* String[] new String[] {file1.getAbsolutePath(),
* file2.getAbsolutePath()}
*
* TransferData包含了很多特定于平台的公用的属性,应用不应该直接去访问这些属性。
* 如果真的有必要去访问这些属性,那么我们可以通过扩展Transfer类来完成对特定平台的额外操作。
*/
textTransfer = TextTransfer.getInstance();
fileTransfer = FileTransfer.getInstance();
// final Color red = display.getSystemColor(SWT.COLOR_GREEN);
// final Color yellow = display.getSystemColor(SWT.COLOR_GRAY);
// tree.addListener(SWT.EraseItem, new Listener() {
// public void handleEvent(Event event) {
// if ((event.detail & SWT.SELECTED) == 0)
// return; /* item not selected */
// int clientWidth = tree.getClientArea().width;
// GC gc = event.gc;
// Color oldForeground = gc.getForeground();
// Color oldBackground = gc.getBackground();
// gc.setForeground(red);
// gc.setBackground(yellow);
// gc.fillGradientRectangle(0, event.y, clientWidth, event.height,
// false);
// gc.setForeground(oldForeground);
// gc.setBackground(oldBackground);
// event.detail &= ~SWT.SELECTED;
// }
// });
shell.setMaximized(true);
// Canvas canvas = new Canvas(shell, SWT.BORDER);
// canvas.setLayout(new FillLayout());
mainSashForm = new SashForm(shell, SWT.HORIZONTAL);
mainSashForm.setBackground(shell.getDisplay().getSystemColor(
SWT.COLOR_TITLE_BACKGROUND));
final Group leftGroup = new Group(mainSashForm, SWT.NONE | SWT.CENTER);
leftGroup.setText("会计科目");
leftGroup.setLayout(new FillLayout());
final TabFolder subtabFolder = new TabFolder(leftGroup, SWT.NONE);
final TabItem subtabItem = new TabItem(subtabFolder, SWT.NONE);
subtabItem.setText("会计科目");
tree = new Tree(subtabFolder, SWT.FULL_SELECTION);
tree.setLinesVisible(true);
addExistItems();
tree.addListener(SWT.Selection, new Listener() ...{
public void handleEvent(Event event) ...{
System.out
.println(tree.getSelection()[0].getData("SetSubData"));
}
});
subtabItem.setControl(tree);
Transfer[] types = new Transfer[] ...{ TextTransfer.getInstance() };
int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
final DragSource treeSource = new DragSource(tree, operations);
treeSource.setTransfer(types);
treeSource.addDragListener(new DragSourceListener() ...{
public void dragStart(DragSourceEvent event) ...{
TreeItem[] selection = ((Tree) ((DragSource) event.widget)
.getControl()).getSelection();
// 只能移动选中并且为最子结点。
// if (selection.length > 0
// && selection[0].getItemCount() == 0) { // 选中并且为最子结点。
if (selection.length > 0) ...{
event.doit = true;
// int selectedCount = ((Tree) ((DragSource)
// event.widget)
// .getControl()).getSelection().length;
// dragSourceItem = new TreeItem[selectedCount];
// for (int i = 0; i < selectedCount; i++) {
// dragSourceItem[i] = selection[i];
// }
} else ...{
event.doit = false;
}
};
public void dragSetData(DragSourceEvent event) ...{
event.data = String.valueOf(typeList.size()); // 最后一个是保存左边树,用于移动节点位置用。;//
// *********
}
public void dragFinished(DragSourceEvent event) ...{
if (event.detail == DND.DROP_MOVE)
protected Tree subtree;
protected Tree preTree;// 单位
protected Tree roomTree;// 科室
protected Table unitTable;// 科室
protected Display display;
protected Shell shell;
protected Tree tree;
protected List newList = new ArrayList();
protected List modifyList = new ArrayList();
protected List deleteList = new ArrayList();
protected Map map = new HashMap();
protected Map mapSave = new HashMap();
protected Object result;
protected SashForm mainSashForm;
protected TextTransfer textTransfer;
protected FileTransfer fileTransfer;
protected Tree[] eachTrees;
// protected TreeItem[] dragSourceItem;
protected int index;
protected Map dataMap;// 缓存
protected List typeList;// 缓存
protected Map relMap;// 缓存
/** *//**
* Create the dialog
*
* @param parent
* @param style
*/
public SetSubSWT(Shell parent, Tree subtree, Map dataMap, List typeList,
Map relMap, int style) ...{
super(parent, style);
this.subtree = subtree;
this.dataMap = dataMap;
this.typeList = typeList;
this.relMap = relMap;
}
// /**
// * Create the dialog
// * @param parent
// */
// public SetSubSWT(Shell parent) {
// this(parent, SWT.NONE);
// }
// /**
// * Launch the application
// *
// * @param args
// */
// public static void main(String[] args) {
// try {
// System.out.println("args[0]==" + args[0]);
// SWTDataViewUtil.httpUrl = args[0] + "/subactionswt.do?action=";
// SetSubSWT window = new SetSubSWT();
// window.open();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
/** *//**
* Open the window
*/
public Object open() ...{
display = getParent().getDisplay();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) ...{
if (!display.readAndDispatch())
display.sleep();
}
return result;
}
/** *//**
* Create contents of the window
*/
protected void createContents() ...{
shell = new Shell();
shell.setLayout(new FillLayout());
shell.setText("会计科目设置");
/**//*
* Transfer是一个可以提供数据在Java representation与platform specific
* representation 之间交互的抽象类.下面是几个format: TextTransfer String "hello
* world" RTFTransfer String "{/rtf1/b/i hello world}" FileTransfer
* String[] new String[] {file1.getAbsolutePath(),
* file2.getAbsolutePath()}
*
* TransferData包含了很多特定于平台的公用的属性,应用不应该直接去访问这些属性。
* 如果真的有必要去访问这些属性,那么我们可以通过扩展Transfer类来完成对特定平台的额外操作。
*/
textTransfer = TextTransfer.getInstance();
fileTransfer = FileTransfer.getInstance();
// final Color red = display.getSystemColor(SWT.COLOR_GREEN);
// final Color yellow = display.getSystemColor(SWT.COLOR_GRAY);
// tree.addListener(SWT.EraseItem, new Listener() {
// public void handleEvent(Event event) {
// if ((event.detail & SWT.SELECTED) == 0)
// return; /* item not selected */
// int clientWidth = tree.getClientArea().width;
// GC gc = event.gc;
// Color oldForeground = gc.getForeground();
// Color oldBackground = gc.getBackground();
// gc.setForeground(red);
// gc.setBackground(yellow);
// gc.fillGradientRectangle(0, event.y, clientWidth, event.height,
// false);
// gc.setForeground(oldForeground);
// gc.setBackground(oldBackground);
// event.detail &= ~SWT.SELECTED;
// }
// });
shell.setMaximized(true);
// Canvas canvas = new Canvas(shell, SWT.BORDER);
// canvas.setLayout(new FillLayout());
mainSashForm = new SashForm(shell, SWT.HORIZONTAL);
mainSashForm.setBackground(shell.getDisplay().getSystemColor(
SWT.COLOR_TITLE_BACKGROUND));
final Group leftGroup = new Group(mainSashForm, SWT.NONE | SWT.CENTER);
leftGroup.setText("会计科目");
leftGroup.setLayout(new FillLayout());
final TabFolder subtabFolder = new TabFolder(leftGroup, SWT.NONE);
final TabItem subtabItem = new TabItem(subtabFolder, SWT.NONE);
subtabItem.setText("会计科目");
tree = new Tree(subtabFolder, SWT.FULL_SELECTION);
tree.setLinesVisible(true);
addExistItems();
tree.addListener(SWT.Selection, new Listener() ...{
public void handleEvent(Event event) ...{
System.out
.println(tree.getSelection()[0].getData("SetSubData"));
}
});
subtabItem.setControl(tree);
Transfer[] types = new Transfer[] ...{ TextTransfer.getInstance() };
int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
final DragSource treeSource = new DragSource(tree, operations);
treeSource.setTransfer(types);
treeSource.addDragListener(new DragSourceListener() ...{
public void dragStart(DragSourceEvent event) ...{
TreeItem[] selection = ((Tree) ((DragSource) event.widget)
.getControl()).getSelection();
// 只能移动选中并且为最子结点。
// if (selection.length > 0
// && selection[0].getItemCount() == 0) { // 选中并且为最子结点。
if (selection.length > 0) ...{
event.doit = true;
// int selectedCount = ((Tree) ((DragSource)
// event.widget)
// .getControl()).getSelection().length;
// dragSourceItem = new TreeItem[selectedCount];
// for (int i = 0; i < selectedCount; i++) {
// dragSourceItem[i] = selection[i];
// }
} else ...{
event.doit = false;
}
};
public void dragSetData(DragSourceEvent event) ...{
event.data = String.valueOf(typeList.size()); // 最后一个是保存左边树,用于移动节点位置用。;//
// *********
}
public void dragFinished(DragSourceEvent event) ...{
if (event.detail == DND.DROP_MOVE)