Java中带复选框的树的级联选择与取消

需要实现如下的功能:

    当选中树中的某一节点时,

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) {
	}
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值