需要实现如下的功能:
当选中树中的某一节点时,
1 、如果该节点是父节点,其下所有子节点应该也被选中,取消选中时亦然 ;
2 、如果该节点是子节点那么选中该节点时,其父节点也应该是被选中状态 ( 父节点下只要有一个子节点处于选中状态这个父节点就应该是选中的,只有当该节点下一个子节点都没有被选中时才是非选中状态 );
3 、如果该节点既是父节点又是子节点那么选中它时,它的所有子节点应同时被选中,其父节点也同时被选中。
其实只要 1 、 2 两个功能实现了,第 3 个功能是必然的。
废话不多说,上代码,如下:
//为了阅读方便将所有类写在了一个类中
package com.syd.test;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
public class Test {
public void run(){
//构建树节点内容,创建10个Person对象,同时创建他们的父子关系
String[] names = new String[]{"Malcolm","Betty","Lily","Fred",
"Gary","William","Linda","Whitney",
"Charles","Joan","Niki","Michael","Karl"};
Person[] p = new Person[10];
for(int i = 1; i<= 10; i++){
p[i-1] = new Person();
p[i-1].setObjectId(10000 + i);
p[i-1].setName(names[i-1]);
switch(i){
case 1:
p[i-1].setPost(Person.POST_BOARD_CHAIRMAN);
break;
case 2:
p[i-1].setPost(Person.POST_GERNERAL_MANAGER);
break;
case 3:
p[i-1].setPost(Person.POST_GERNERAL_MANAGER);
break;
case 4:
p[i-1].setPost(Person.POST_ASSISTANT_MANAGER);
break;
default:
p[i-1].setPost(Person.POST_EMPLOREE);
break;
}
}
for(int i=1;i<=2;i++){//董事长下属两个总经理
p[0].addChild(p[i]);
p[i].setParent(p[0]);
}
p[1].addChild(p[3]);//总经理1下属1个副总
for(int i=4;i<=6;i++){
p[3].addChild(p[i]);//职员1-3隶属副总
p[i].setParent(p[3]);
}
for(int i=7;i<=9;i++){
p[2].addChild(p[i]);//职员1-3隶属副总
p[i].setParent(p[2]);
}
/***************************此处以上都是在创建Person对象***********************************/
final Display display = Display.getDefault();
final Shell shell = new Shell();
shell.setSize(500, 375);
final TreeViewer viewer = new TreeViewer(shell, SWT.CHECK|SWT.H_SCROLL);
final Tree tree = viewer.getTree();
tree.setBounds(83, 75, 264, 185);
PersonViewerContentProvider provider = new PersonViewerContentProvider();
viewer.setLabelProvider(provider);
viewer.setContentProvider(provider);
viewer.setInput(new Person[]{p[0]});
tree.addSelectionListener(new SelectionListener(){
@Override
public void widgetDefaultSelected(SelectionEvent e) {}
@Override
public void widgetSelected(SelectionEvent e) {
TreeItem item = (TreeItem) e.item;
tree.setSelection(item);
List authorities = new ArrayList<Object>();
checkItem(item,authorities);//该方法是实现级联操作的关键
}
});
shell.open();
shell.setLayout(new FillLayout());
shell.layout();
while(!shell.isDisposed()){
if(!display.readAndDispatch()){
display.sleep();
}
}
display.dispose();
}
private void checkItem(TreeItem item,List<Object> authorities){
checkItem(item,authorities,false,false);
}
private void checkItem(TreeItem item, List<Object> allCheckedElements,boolean isParent,boolean isChild){
//此处树已经构建完成,所以在判断是父节点还是子节点是直接根据树的物理结构判断,而不需要再考虑逻辑
if(!isChild){
if(item.getItemCount() != 0)
isParent = true;
}
if(item.getParentItem() != null){
isChild = true;
} else {
isChild = false;
}
if (isParent) { // 是父节点时应该选中该选中该节点时级联选中其下的所有子节点,取消选中时同理
TreeItem[] children = item.getItems();
Object o = item.getData();
if (item.getChecked()) { //选中该父节点时,它所有的子节点也要被选中
if(!allCheckedElements.contains(o))
allCheckedElements.add(o);// 将选中的节点放入到allCheckedElements中
for (int i = 0; i < children.length; i++) {
children[i].setChecked(true);
checkItem(children[i],allCheckedElements);
}
} else {// 取消选中时它的所有子节点也同时被取消选中
if(allCheckedElements.contains(o))
allCheckedElements.remove(o);//如果选中的节点之前在allCheckedElements中,则移除
for (int i = 0; i < children.length; i++) {
children[i].setChecked(false);
checkItem(children[i],allCheckedElements);
}
}
}
if (isChild) {// 不是父节点
TreeItem[] brotheres = item.getParentItem().getItems();// 获得它的所有的兄弟节点
Object o = item.getData();
if (item.getChecked()) {
if(!allCheckedElements.contains(o))
allCheckedElements.add(o);// 将选中的节点加入到allCheckedElements中
} else {
if(allCheckedElements.contains(o))//如果之前allCheckedElements中没有包含该节点则加入
allCheckedElements.remove(o);
}
boolean hasBrotherChecked = false;
for (TreeItem brother : brotheres) {// 判断它的兄弟节点中有没有被选中的
if (brother.getChecked()) {
hasBrotherChecked = true;
break;
}
}
if(hasBrotherChecked){//如果兄弟节点中有被选中的那么父节点也被选中
item.getParentItem().setChecked(true);
Object po = item.getParentItem().getData();
if(!allCheckedElements.contains(po))
allCheckedElements.add(po);
checkItem(item.getParentItem(),allCheckedElements,false,true);
} else {//相么如果兄弟节点中一个都没有被选中的,那么父节点也不应被选中
item.getParentItem().setChecked(false);
Object po = item.getParentItem().getData();
if(allCheckedElements.contains(po))
allCheckedElements.remove(po);
checkItem(item.getParentItem(),allCheckedElements,false,true);
}
}
}
public static void main(String[] args) {
Test t = new Test();
t.run();
}
}
class Person {
public final static String POST_GERNERAL_MANAGER = "总经理";
public final static String POST_ASSISTANT_MANAGER = "副经理";
public final static String POST_BOARD_CHAIRMAN = "董事长";
public final static String POST_EMPLOREE = "职工";
private long objectId; //ID号
private String name; //姓名
private String post; //职务
private Person parent; //上级
private List<Person> children = new ArrayList<Person>(); //下属
public long getObjectId() {
return objectId;
}
public void setObjectId(long objectId) {
this.objectId = objectId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPost() {
return post;
}
public void setPost(String post) {
this.post = post;
}
public Person getParent() {
return parent;
}
public void setParent(Person parent) {
this.parent = parent;
}
public List<Person> getChildren() {
return children;
}
public void setChildren(List<Person> children) {
this.children = children;
}
public void addChild(Person p){
children.add(p);
}
}
class PersonViewerContentProvider implements ITreeContentProvider,
ILabelProvider {
@Override
public Object[] getChildren(Object parentElement) {
return ((Person)parentElement).getChildren().toArray();
}
@Override
public Object getParent(Object element) {
return ((Person)element).getParent();
}
@Override
public String getText(Object element) {
Person p = (Person)element;
return p.getName() + "<" + p.getPost() + ">";
}
@Override
public boolean hasChildren(Object element) {
Person p = (Person)element;
return p.getChildren() != null && p.getChildren().size() != 0;
}
@Override
public Object[] getElements(Object inputElement) {
return (Object[]) inputElement;
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
@Override
public Image getImage(Object element) {
return null;
}
@Override
public void addListener(ILabelProviderListener listener) {
}
@Override
public boolean isLabelProperty(Object element, String property) {
return false;
}
@Override
public void removeListener(ILabelProviderListener listener) {
}
}