一个JTree节点添加、删除和修改的例子

时间:2022-09-05 16:08:06
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventObject;

import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreePath;

/**
 * @ClassName: TreeDemo9
 * @Description: 以key,value对为节点数据的树,包括树的节点显示、节点删除、节点添加、节点修改
 * @author Li
 * @date 2012-4-29 下午02:32:59
 * 
 */
public class TreeDemo9 extends JFrame {
	private static final long serialVersionUID = 1L;
	private JTree itree;
	private JTextField ifld;

	public TreeDemo9() {
		itree = new JTree();

		// 插入初始数据
		DefaultMutableTreeNode root = new DefaultMutableTreeNode(new KeyValue(
				"lhl", "god"));
		DefaultMutableTreeNode other = new DefaultMutableTreeNode(new KeyValue(
				"tongtong", "tiandao"));
		root.add(other);
		other = new DefaultMutableTreeNode(new KeyValue("xidian", "myschool"));
		root.add(other);
		DefaultTreeModel model = new DefaultTreeModel(root);
		itree.setModel(model);

		// 显示包括子节点的分支节点的把手
		itree.setShowsRootHandles(true);

		// 设置单元编辑器
		// 使用DefaultTreeCellEditor帮助控制何时开启单元编辑器及其它的位置
		itree.setCellEditor(new DefaultTreeCellEditor(itree,
				new DefaultTreeCellRenderer(), new MyTreeCellEditor()));
		itree.setEditable(true);

		// 树的节点信息显示,即树节点选择事件
		// 设置选择模型,只能一次选择一个节点
		itree.getSelectionModel().setSelectionMode(
				DefaultTreeSelectionModel.SINGLE_TREE_SELECTION);
		itree.addTreeSelectionListener(new TreeSelectionListener() {

			@Override
			public void valueChanged(TreeSelectionEvent arg0) {
				JTree tree = (JTree) arg0.getSource();
				DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
						.getLastSelectedPathComponent();
				if(node!=null){//可能关闭分支节点,这时候没有被选中的节点
					KeyValue keyvalue = (KeyValue) node.getUserObject();
					ifld.setText(keyvalue.value);
				}else
					ifld.setText("");
			}
		});

		// 添加节点删除,节点新建的右键
		JPopupMenu menu=new JPopupMenu();
		JMenuItem item=new JMenuItem("add");
		item.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("add node!!");
				DefaultMutableTreeNode node=(DefaultMutableTreeNode) itree.getLastSelectedPathComponent();
				DefaultTreeModel model=(DefaultTreeModel)itree.getModel();
				DefaultMutableTreeNode newnode=new DefaultMutableTreeNode(new KeyValue("new", "noe"));
				model.insertNodeInto(newnode ,node, node.getChildCount());
				itree.scrollPathToVisible(new TreePath(newnode.getPath()));
				itree.setSelectionPath(new TreePath(newnode.getPath()));
			}
		});
		menu.add(item);
		
		item=new JMenuItem("delete");
		item.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				System.out.println("delete node!!");
				DefaultMutableTreeNode node=(DefaultMutableTreeNode)itree.getLastSelectedPathComponent();
				DefaultTreeModel model=(DefaultTreeModel)itree.getModel();
				model.removeNodeFromParent(node);
				
				itree.setSelectionRow(0);
			}
		});
		menu.add(item);
		itree.addMouseListener(new MyTreeMouseAdapter(menu));
		add(new JScrollPane(itree), BorderLayout.WEST);

		ifld = new JTextField();
		add(ifld, BorderLayout.CENTER);
	}

	public static void main(String[] args) {
		TreeDemo9 it = new TreeDemo9();
		it.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		it.pack();
		
		it.setLocationRelativeTo(null);
//		it.setLocation(it.getX() - 150, it.getY() - 150);
		it.setSize(300, 300);
		
		it.setVisible(true);
	}
}

class MyTreeMouseAdapter extends MouseAdapter {
	JPopupMenu imenu;

	public MyTreeMouseAdapter(JPopupMenu amenu) {
		imenu = amenu;
	}

	@Override
	// 鼠标发开和鼠标按下都调用显示右键菜单,否则可能显示不出来,swing的bug吧
	public void mousePressed(MouseEvent e) {
		showPopupMenu(e);
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		showPopupMenu(e);
	}

	private void showPopupMenu(MouseEvent e) {
		if (e.isPopupTrigger()) {
			JTree tree = (JTree) e.getSource();
			TreePath path = tree.getPathForLocation(e.getX(), e.getY());
			
			if (path != null&&path.getParentPath()!=null) {//没有父节点就是根节点
				imenu.show(tree, e.getX(), e.getY());
				tree.setSelectionPath(path);
			}
		}
	}
}

class MyTreeCellEditor extends AbstractCellEditor implements TreeCellEditor {
	private static final long serialVersionUID = 1L;
	private KeyValue ikeyvalue;
	private KeyValueFrame iframe;
	private JLabel ilabel;

	public MyTreeCellEditor() {
		iframe = new KeyValueFrame(this);
		ilabel = new JLabel();
	}

	@Override
	public Object getCellEditorValue() {
		return ikeyvalue;
	}

	@Override
	public Component getTreeCellEditorComponent(JTree arg0, Object arg1,
			boolean arg2, boolean arg3, boolean arg4, int arg5) {
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) arg1;
		ikeyvalue = (KeyValue) node.getUserObject();
		ilabel.setText(ikeyvalue.key);
		ilabel.setForeground(Color.red);
		ilabel.setBackground(Color.red);// 没有效果,可能是JTree自己调整了吧
		iframe.setKeyValue(ikeyvalue.key, ikeyvalue.value);
		return ilabel;
	}

	@Override
	public boolean isCellEditable(EventObject arg0) {
		return true;
	}

	@Override
	public boolean shouldSelectCell(EventObject arg0) {
		iframe.pack();
		iframe.setLocationRelativeTo(null);
//		iframe.setLocation(iframe.getX() - iframe.getWidth() / 2, iframe.getY()
//				- iframe.getHeight() / 2);
		iframe.setVisible(true);
		
		return true;
	}

	@Override
	public void cancelCellEditing() {
		iframe.setVisible(false);
		super.cancelCellEditing();
	}

	@Override
	public boolean stopCellEditing() {
		iframe.setVisible(false);
		KeyValue buf = iframe.getKeyValue();

		if (buf.key.equals("")) {
			super.stopCellEditing();
			return false;
		} else {
			ikeyvalue = buf;
			super.stopCellEditing();// 修改getCellEditorValue返回值后,在通知其他监听者
			return true;
		}
	}
}

class KeyValue {
	public String key;
	public String value;

	public KeyValue(String akey, String avalue) {
		key = akey;
		value = avalue;
	}

	@Override
	public String toString() {
		return key;
	}
}

        一个JTree的例子,参考网页包括 http://docs.oracle.com/javase/tutorial/uiswing/components/tree.htmlhttp://www.iteedu.com/plang/java/jtswingchxshj/index.php。其中单元编辑器部分是一种风格,swing一些复杂的组件都是使用的它。