在SWT/JFace中,带复选框树最好使用ContainerCheckedTreeViewer(或者CheckedTreeViewer)来实现,今天遇到直接使用tree来实现的。
简单备记:
import java.awt.image.BufferedImage;
import java.io.File;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.filechooser.FileSystemView;
import javax.swing.plaf.IconUIResource;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.internal.UIPlugin;
/**
* <p>
* Title: MultiDirectoryDialog.java
* </p>
* <p>
* Description: 文件选择框,支持多选
* </p>
*
*/
public class MultiDirectoryDialog extends Dialog {
// 菜单提示
private String message = "";
private Shell parent;
// 列表树
private Tree tree;
// 用来获取系统文件的相关信息
private FileSystemView fsv;
// 用来存放选择的文件夹,用分号隔开
private StringBuilder resultFile = new StringBuilder("");
/**
* 构造方法
*
* @param parent
* 父类
*/
public MultiDirectoryDialog(Shell parent) {
super(parent);
this.parent = parent;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets
* .Composite)
*/
protected Control createDialogArea(Composite parent) {
parent.setDragDetect(false);
Composite container = (Composite) super.createDialogArea(parent);
container.setLayout(new FormLayout());
final Label showTipLabel = new Label(container, SWT.NONE | SWT.MULTI);
showTipLabel.setText(message);
final FormData fd_showTipLabel = new FormData();
fd_showTipLabel.top = new FormAttachment(0, 15);
fd_showTipLabel.bottom = new FormAttachment(0, 32);
fd_showTipLabel.right = new FormAttachment(0, 170);
fd_showTipLabel.left = new FormAttachment(0, 30);
showTipLabel.setLayoutData(fd_showTipLabel);
final Composite treeComposite = new Composite(container, SWT.BORDER);
treeComposite.setDragDetect(false);
treeComposite.setLayout(new FormLayout());
// treeComposite.set
// scrolledComposite.setAlwaysShowScrollBars(true);
final FormData fd_scrolledComposite = new FormData();
fd_scrolledComposite.right = new FormAttachment(100, 0);
fd_scrolledComposite.left = new FormAttachment(0, 0);
fd_scrolledComposite.bottom = new FormAttachment(100, 0);
fd_scrolledComposite.top = new FormAttachment(0, 50);
treeComposite.setLayoutData(fd_scrolledComposite);
// 新建树
tree = new Tree(treeComposite, SWT.DEFAULT);
final FormData fd_tree = new FormData();
fd_tree.left = new FormAttachment(0, 5);
fd_tree.bottom = new FormAttachment(0, 300);
fd_tree.top = new FormAttachment(0, 0);
fd_tree.right = new FormAttachment(0, 400);
tree.setLayoutData(fd_tree);
treeComposite.setData(tree);
// 为树增加单击方法
tree.addListener(SWT.Expand, new Listener() {
public void handleEvent(final Event event) {
final TreeItem item = (TreeItem) event.item;
TreeItem[] items = item.getItems();
for (int i = 0; i < items.length; i++) {
if (items[i].getData() != null)
return;
items[i].dispose();
}
// 初始化该文件下的节点
File file = (File) item.getData();
File[] childFile = file.listFiles();
for (File sfile : childFile) {
if (sfile.isDirectory()) {
initFile(item, sfile);
}
}
}
});
// 获取系统文件信息
fsv = FileSystemView.getFileSystemView();
File[] file = fsv.getRoots();
TreeItem item = new TreeItem(this.tree, SWT.NONE);
String fileName = file[0].getName();
item.setText(fileName);
item.setData(file[0]);
Image img = getIcon(file[0]);
if (img != null)
item.setImage(img);
// new TreeItem(item, 0);
listFile(item, file[0], 1);
return container;
}
/**
* 本类用来初始化文件夹下的文件夹
*
* @param treeitem
* 父节点
* @param file
* 要初始化的文件夹
* @param flag
* 0:由外部调用,其它:递归调用
*/
private void listFile(TreeItem treeitem, File file, int flag) {
File[] childFile = file.listFiles();
if (flag == 0) {// 如果是外部调用,则再初始一级,以用来显示图标前的十一号。
for (File sfile : childFile) {
if (sfile.isDirectory()) {
// 初始化item的相关数据
TreeItem item = initFile(treeitem, sfile);
// 初始化下一级item
listFile(item, sfile, 1);// 只多这一行
}
}
} else {// 如果是自身调用,则说明已经为第二级文件夹,不需要再初始化下一级
for (File sfile : childFile) {
if (sfile.isDirectory()) {
initFile(treeitem, sfile);
}
}
}
}
/**
* 初始化item的相关数据
*
* @param treeitem
* 要初始化item的父item
* @param file
* 初始化item对应的file
* @return 初始化后的item
*/
private TreeItem initFile(TreeItem treeitem, File file) {
TreeItem item = new TreeItem(treeitem, SWT.NONE);
item.setText(fsv.getSystemDisplayName(file));
item.setData(file);
Image img = getIcon(file);
if (img != null)
item.setImage(img);
// 如果还是文件夹,则加一个空节点,以使十号显示出来
if (file.isDirectory())
new TreeItem(item, 0);
return item;
}
/**
* 获取文件图标
*
* @param file
* 要获取图标的文件
* @return 图标
*/
public Image getIcon(File file) {
ImageData imageData = null;
// 取得awt的icon对像并转化为swt的image对像
Icon icon = fsv.getSystemIcon(file);
if (icon instanceof IconUIResource) {
} else {
// BufferedImage bi = ImageConvertor.getBufferedImage((ImageIcon)
// icon);
// imageData = ImageConvertor.getImageData(bi);
// imageData = new Image(Display.getDefault(),50,50).getImageData();
}
Image img = null;
if (imageData != null)
img = new Image(parent.getDisplay(), imageData);
return img;
}
/**
* Create contents of the button bar
*
* @param parent
*/
@Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.OK_ID, "确定", true);
createButton(parent, IDialogConstants.CANCEL_ID, "取消", false);
}
/**
SWT.MULTI创建出可以让用户作出多重选取的tree。SWT.CHECK样式的Tree会产生checkbox的Tree。如果使用了SWT.CHECK的样式,就需要判断哪些项目被选取了。通过调用TreeItem的getChecked()来判断某个项目是否被checked。下面的程序在循环中判断每个TreeItem的状态:
TreeItem[] tia=t.getItems();
for(int i=0;i<tia.length;i++){
if(tia[i].getChecked()){
System.out.print("Checked");
}
TreeItem []child=tia[i].getItems();
for(int n=0;n<child.length;n++)
if(child[n].getChecked())
System.out.print("Checked");
}
以上的代码只能用在仅有一层子项目的tree上。多层的tree需要循环运算来处理。
SWT.CHECK样式的Tree对象在你需要让用户对Tree作出多重选取但又不想要SWT.MULTI模式的额外成本的时候是合适的(但若是要使用选取出的TreeItem来采取某些像是产生list内容这样的动作时则不适用)
*/
protected void buttonPressed(int buttonId) {
if (buttonId == IDialogConstants.OK_ID) {
TreeItem[] treeitem = tree.getItems();
for (int i = 0; i < treeitem.length; i++) {
if (treeitem[i].getChecked()) {
if (treeitem[i].getChecked()) {
File file = (File) treeitem[i].getData();
resultFile.append(file.getPath()).append(";");
}
}
TreeItem[] child = treeitem[i].getItems();
for (int n = 0; n < child.length; n++)
if (child[n].getChecked()) {
File file = (File) child[n].getData();
resultFile.append(file.getPath()).append(";");
}
}
System.out.println(resultFile.toString());
}
super.buttonPressed(buttonId);
}
/**
* 设置 message
*
* @return
*/
public String getMessage() {
return message;
}
/**
* 获取message
*
* @param message
*/
public void setMessage(String message) {
this.message = message;
}
/**
* @return
*/
public StringBuilder getResultFile() {
return resultFile;
}
/**
* @param resultFile
*/
public void setResultFile(StringBuilder resultFile) {
this.resultFile = resultFile;
}
public static void main(String[] args) {
final Display display = Display.getDefault();
final Shell shell = new Shell(display, SWT.ON_TOP | SWT.CLOSE);
shell.setSize(327, 253);
Dialog dialog = new MultiDirectoryDialog(shell);
if (dialog.open() == IDialogConstants.OK_ID) {// 是否单击“确定”按钮
System.out.println("helo");
}
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}