`
yadsun
  • 浏览: 181388 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

 

 

 

6
0
分享到:
评论
2 楼 yadsun 2010-06-22  
ylc2010 写道
有bug,选择与选中事件不分。。。

我这边没出现你说的情况,不知道你是怎么操作的
1 楼 ylc2010 2010-06-18  
有bug,选择与选中事件不分。。。

相关推荐

    TreeControl复选框:选中某个节点的复选框后,自动选中子节点的复选框

    复选框是用户交互的一种常见元素,允许用户选择或取消选择某个选项。在TreeControl中,每个节点可以有一个与之关联的复选框,用户可以通过点击这个复选框来改变节点的状态。 标题和描述所提到的“选中某个节点的复...

    带有checkbox的TREE列表级联的选择子栏目的JAVA标签形式的实现

    本文将详细讲解如何实现一个带有复选框(Checkbox)的树形列表(TREE LIST)的级联选择功能,以及相关的Java标签形式实现。这种功能常见于权限管理、组织结构选择等场景,让用户能够方便地进行多层级的勾选操作。 ...

    checknode(树型)

    在这个特定的例子中,我们关注的是"checknode(树型)",这意味着它是在JTree的基础上增加了复选框功能,使得用户能够对树中的节点进行选择操作。下面我们将详细探讨这个主题。 首先,`CheckNodeTreeExample.java`...

    TreeCheckBox

    在描述中提到的“在树型控件Tree中可以实现CheckBox的复选内容”,意味着用户不仅能在树节点上看到文本信息,还能通过复选框对每个节点进行选择或取消选择,以表示他们对某项内容的同意、选择或者关注。 在深入讨论...

    ztree全包 core +check + exhide

    zTree的核心功能、复选框功能和隐藏节点功能可以灵活结合使用,例如在权限管理中,可以根据用户角色权限隐藏部分节点,同时提供复选框进行多选操作。在文件管理系统中,可利用动态加载和隐藏功能,展现层级清晰的...

    功能强大的自定义TreeView控件.rar

    CheckBoxes属性使得每个节点都有一个复选框,用户可以通过勾选这些复选框来选择或取消选择节点。默认情况下,CheckBoxes功能并不提供级联选择,即选中一个节点不会影响它的父节点或子节点。 3. **自定义功能** 这...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例048 复选框控件数组 59 实例049 用数组反转字符串 60 3.3 数组排序与查询 61 实例050 使用选择排序法 61 实例051 使用冒泡排序法 62 实例052 使用快速排序法 64 实例053 使用直接插入法 65 实例054 使用sort方法...

    dtree实现的树支持多选

    4. **节点渲染**:DTree的每个节点通常由HTML元素(如`&lt;li&gt;`和`&lt;span&gt;`)组成,其中包含一个复选框元素(`&lt;input type="checkbox"&gt;`)用于表示可选状态。通过CSS定义样式,可以定制节点的外观。 5. **事件处理**:...

    精通javascript

    2.选择浏览器的“工具”-“安全”-“本地Intranet”-“自定义级别”-“活动脚本”中选用“禁用”单选框 3.在浏览器中输入下述地址:http://localhost/1.2.htm • 1.1.htm 多段代码相互调用 • 1.2....

    IT软件开发常用英语词汇经典大全.doc

    17. **复选框(Check Box)**:用户界面元素,用户可以用来选择或取消选择一个选项。 18. **数据库的级联操作(Cascading Delete/Update)**:当主记录被删除或更新时,自动处理相关联记录的删除或更新。 19. **...

    精通JavaScript

    2.选择浏览器的“工具”-“安全”-“本地Intranet”-“自定义级别”-“活动脚本”中选用“禁用”单选框 3.在浏览器中输入下述地址:http://localhost/1.2.htm • 1.1.htm 多段代码相互调用 • 1.2....

    javaSE代码实例

    6.9.2 Java中的GregorianCalendar类 96 6.9.3 擅用系统已有类的思想 98 6.10 小结 99 第7章 访问控制——Java世界的卫兵 100 7.1 包的使用 100 7.1.1 声明创建包 100 7.1.2 引入包内的资源 102 7.1.3...

Global site tag (gtag.js) - Google Analytics