这是刚刚写完的,一个使JTree节点有JCheckbox外观的类。
最近的工作需要,对项目的菜单加入权限设置。
所以打算用树型控件来进行操作,没办法,只好改造swing的JTree了。
网上有个JTree with CheckBoxes的例子
http://jroller.com/page/santhosh?entry=jtree_with_checkboxes
总觉得比较麻烦,正好自己有时间,还是自己写一个吧。
代码在下面,贴出来分享一下,没什么时间写文档,大概看一下吧。
基本上就是用一个HashMap记录状态
用一个TreeSelectionListener修改状态
再就是用Renderer修改外观
还有就是也用到了三态的JCheckbox类
总体上不是很麻烦,感觉比JTree with CheckBoxes的例子简单多了
只是里面写起来有点饶,呵呵
有更好的方法欢迎提出来讨论,有空我会继续完善的。
//MyTreeWithCheckbox.java
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import java.awt.Component;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import java.util.*;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import java.awt.Component;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import java.util.*;
/**
* 自己写的一个使JTree节点有JCheckbox外观的类
* 用了泛型,所以要jdk1.5编译,之前jdk版本的话把集合类写法改回去就可以了
* <p>
* @version 1.0 12/06/2006
* @author Thatboy
*/
public class MyTreeWithCheckbox {
//用一个HashMap来保存每个节点的选择状态
private HashMap<TreeNode, TristateCheckBox.State> hm = new HashMap<TreeNode, TristateCheckBox.State>();
* 自己写的一个使JTree节点有JCheckbox外观的类
* 用了泛型,所以要jdk1.5编译,之前jdk版本的话把集合类写法改回去就可以了
* <p>
* @version 1.0 12/06/2006
* @author Thatboy
*/
public class MyTreeWithCheckbox {
//用一个HashMap来保存每个节点的选择状态
private HashMap<TreeNode, TristateCheckBox.State> hm = new HashMap<TreeNode, TristateCheckBox.State>();
public MyTreeWithCheckbox(JTree jTree) {
DefaultMutableTreeNode root = (DefaultMutableTreeNode) jTree.getModel().getRoot();
for (Enumeration em = root.depthFirstEnumeration(); em.hasMoreElements(); ) {
hm.put((DefaultMutableTreeNode) em.nextElement(), TristateCheckBox.NOT_SELECTED);
}
jTree.setCellRenderer(new MyTreeWithCheckboxRenderer());
jTree.addTreeSelectionListener(new MyTreeWithCheckboxSelectionListener());
}
/** 返回所有选中的路径 */
public TreePath[] getSelectionPaths() {
Iterator it = hm.keySet().iterator();
ArrayList<TreePath> al = new ArrayList<TreePath>();
while (it.hasNext()) {
DefaultMutableTreeNode o = (DefaultMutableTreeNode) it.next();
if (o.isLeaf() && ((TristateCheckBox.State) hm.get(o)).equals(TristateCheckBox.SELECTED)) {
al.add(new TreePath(o.getPath()));
}
}
return (TreePath[]) al.toArray(new TreePath[0]);
}
DefaultMutableTreeNode root = (DefaultMutableTreeNode) jTree.getModel().getRoot();
for (Enumeration em = root.depthFirstEnumeration(); em.hasMoreElements(); ) {
hm.put((DefaultMutableTreeNode) em.nextElement(), TristateCheckBox.NOT_SELECTED);
}
jTree.setCellRenderer(new MyTreeWithCheckboxRenderer());
jTree.addTreeSelectionListener(new MyTreeWithCheckboxSelectionListener());
}
/** 返回所有选中的路径 */
public TreePath[] getSelectionPaths() {
Iterator it = hm.keySet().iterator();
ArrayList<TreePath> al = new ArrayList<TreePath>();
while (it.hasNext()) {
DefaultMutableTreeNode o = (DefaultMutableTreeNode) it.next();
if (o.isLeaf() && ((TristateCheckBox.State) hm.get(o)).equals(TristateCheckBox.SELECTED)) {
al.add(new TreePath(o.getPath()));
}
}
return (TreePath[]) al.toArray(new TreePath[0]);
}
class MyTreeWithCheckboxSelectionListener implements TreeSelectionListener {
public void valueChanged(TreeSelectionEvent e) {
JTree jTree = (JTree) (e.getSource());
DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
if (node == null) {
return;
}
// 修改当前节点的状态
if (((TristateCheckBox.State) hm.get(node)).equals(TristateCheckBox.SELECTED)) {
hm.put(node, TristateCheckBox.NOT_SELECTED);
} else {
hm.put(node, TristateCheckBox.SELECTED);
}
updateAllParentNodes(node);
updateAllChildNodes(node);
jTree.setSelectionPath(null);
jTree.repaint();
}
/** 用递归方法修改从当前节点到根节点的所有节点的状态*/
public void updateAllParentNodes(DefaultMutableTreeNode node) {
TristateCheckBox.State status = (TristateCheckBox.State) hm.get(node);
if (node.isRoot()) {
return;
}
hm.put(node.getParent(), status);
for (Enumeration em = node.getParent().children(); em.hasMoreElements(); ) {
DefaultMutableTreeNode tn = (DefaultMutableTreeNode) em.nextElement();
if (!((TristateCheckBox.State) hm.get(tn)).equals(status)) {
hm.put(node.getParent(), TristateCheckBox.DONT_CARE);
break;
}
}
updateAllParentNodes((DefaultMutableTreeNode) node.getParent());
}
/** 用递归方法修改以当前节点为根的子树的所有节点的状态*/
public void updateAllChildNodes(DefaultMutableTreeNode node) {
TristateCheckBox.State status = (TristateCheckBox.State) hm.get(node);
for (Enumeration em = node.depthFirstEnumeration(); em.hasMoreElements(); ) {
DefaultMutableTreeNode tn = (DefaultMutableTreeNode) em.nextElement();
hm.put(tn, status);
}
}
}
public void valueChanged(TreeSelectionEvent e) {
JTree jTree = (JTree) (e.getSource());
DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
if (node == null) {
return;
}
// 修改当前节点的状态
if (((TristateCheckBox.State) hm.get(node)).equals(TristateCheckBox.SELECTED)) {
hm.put(node, TristateCheckBox.NOT_SELECTED);
} else {
hm.put(node, TristateCheckBox.SELECTED);
}
updateAllParentNodes(node);
updateAllChildNodes(node);
jTree.setSelectionPath(null);
jTree.repaint();
}
/** 用递归方法修改从当前节点到根节点的所有节点的状态*/
public void updateAllParentNodes(DefaultMutableTreeNode node) {
TristateCheckBox.State status = (TristateCheckBox.State) hm.get(node);
if (node.isRoot()) {
return;
}
hm.put(node.getParent(), status);
for (Enumeration em = node.getParent().children(); em.hasMoreElements(); ) {
DefaultMutableTreeNode tn = (DefaultMutableTreeNode) em.nextElement();
if (!((TristateCheckBox.State) hm.get(tn)).equals(status)) {
hm.put(node.getParent(), TristateCheckBox.DONT_CARE);
break;
}
}
updateAllParentNodes((DefaultMutableTreeNode) node.getParent());
}
/** 用递归方法修改以当前节点为根的子树的所有节点的状态*/
public void updateAllChildNodes(DefaultMutableTreeNode node) {
TristateCheckBox.State status = (TristateCheckBox.State) hm.get(node);
for (Enumeration em = node.depthFirstEnumeration(); em.hasMoreElements(); ) {
DefaultMutableTreeNode tn = (DefaultMutableTreeNode) em.nextElement();
hm.put(tn, status);
}
}
}
class MyTreeWithCheckboxRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 1L;
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
TristateCheckBox checkBox = new TristateCheckBox(value.toString());
checkBox.setOpaque(false);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
checkBox.setState(((TristateCheckBox.State) hm.get(node)));
return checkBox;
}
}
}
private static final long serialVersionUID = 1L;
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
TristateCheckBox checkBox = new TristateCheckBox(value.toString());
checkBox.setOpaque(false);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
checkBox.setState(((TristateCheckBox.State) hm.get(node)));
return checkBox;
}
}
}
//顺便写个测试代码吧 TreeDemo.java
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import java.awt.BorderLayout;
public class TreeDemo extends JPanel {
private JTree tree;
public TreeDemo() {
this.setLayout(new BorderLayout());
tree = new JTree();
//用MyTreeWithCheckbox来实现用JCheckbox做节点的JTree
new MyTreeWithCheckbox(tree);
JScrollPane treeView = new JScrollPane(tree);
treeView.setPreferredSize(new Dimension(500, 400));
add(treeView);
}
private JTree tree;
public TreeDemo() {
this.setLayout(new BorderLayout());
tree = new JTree();
//用MyTreeWithCheckbox来实现用JCheckbox做节点的JTree
new MyTreeWithCheckbox(tree);
JScrollPane treeView = new JScrollPane(tree);
treeView.setPreferredSize(new Dimension(500, 400));
add(treeView);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TreeDemo newContentPane = new TreeDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TreeDemo newContentPane = new TreeDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}