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.html和 http://www.iteedu.com/plang/java/jtswingchxshj/index.php。其中单元编辑器部分是一种风格,swing一些复杂的组件都是使用的它。