Swing树结构节点渲染JCheckbox
来源:互联网 发布:java里定义全局变量 编辑:程序博客网 时间:2024/05/07 17:55
package tip;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class MyTreeWithCheckbox{
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(); ) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) em.nextElement();
hm.put(node, TristateCheckBox.NOT_SELECTED);
}
jTree.setCellRenderer(new MyTreeWithCheckboxRenderer());
jTree.addMouseListener(new MyTreeWithCheckboxSelectionListener());
}
/**
*
* 返回所有选中的路径
*/
public TreePath[] getSelectionPaths() {
Iterator<TreeNode> 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 MouseListener {
int i = 0;
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();
}
/**
* 树节点添加点击处理事件
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
*/
@Override
public void mouseClicked(MouseEvent mouseevent)
{
int i = 0;
Iterator<TreeNode> num =hm.keySet().iterator();
while(num.hasNext()){
DefaultMutableTreeNode node = (DefaultMutableTreeNode) num.next();
ParamViewUserObject obj = (ParamViewUserObject)node.getUserObject();
if(obj.isMo()&&obj.isSelected()){
i++;
}
}
JTree jTree = (JTree) (mouseevent.getSource());
DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
if (node == null) {
return;
}
ParamViewUserObject obj = (ParamViewUserObject)node.getUserObject();
if(node.isLeaf()||obj.isMo()){
// 修改当前节点的状态
if (((TristateCheckBox.State) hm.get(node)).equals(TristateCheckBox.SELECTED)) {
obj.setSelected(false);
hm.put(node, TristateCheckBox.NOT_SELECTED);
} else {
if(i<5){
obj.setSelected(true);
hm.put(node, TristateCheckBox.SELECTED);
}else{
//null代表的适用于展示在哪里
JOptionPane.showMessageDialog(null, "处于性能考虑,目前最多可选5个MO级别参数");
}
}
updateAllParentNodes(node);
updateAllChildNodes(node);
jTree.setSelectionPath(null);
jTree.repaint();
}
}
/**
* 用递归方法修改从当前节点到根节点的所有节点的状态
* @param node
*/
public void updateAllParentNodes(DefaultMutableTreeNode node) {
int i = 0;
TristateCheckBox.State status = (TristateCheckBox.State) hm.get(node);
if (node.isRoot()) {
return;
}
if(status.equals(TristateCheckBox.SELECTED)){
((ParamViewUserObject)(((DefaultMutableTreeNode)(node.getParent())).getUserObject())).setSelected(true);
hm.put(node.getParent(), TristateCheckBox.SELECTED);
}else{
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.SELECTED);
break;
}
i++;
}
}
if(i == node.getParent().getChildCount()){
((ParamViewUserObject)(((DefaultMutableTreeNode)(node.getParent())).getUserObject())).setSelected(false);
hm.put(node.getParent(), status);
}
updateAllParentNodes((DefaultMutableTreeNode) node.getParent());
}
/**
* 用递归方法修改以当前节点为根的子树的所有节点的状态
*
* @param node
*/
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();
if(status.equals(TristateCheckBox.SELECTED)){
((ParamViewUserObject)tn.getUserObject()).setSelected(true);
}else{
((ParamViewUserObject)tn.getUserObject()).setSelected(false);
}
hm.put(tn, status);
}
}
@Override
public void mouseEntered(MouseEvent mouseevent)
{
}
@Override
public void mouseExited(MouseEvent mouseevent)
{
}
@Override
public void mousePressed(MouseEvent mouseevent)
{
}
@Override
public void mouseReleased(MouseEvent mouseevent)
{
}
}
/**
* 给mo以及leaf节点渲染checkbox的类
*
*/
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) {
ParamViewUserObject obj = (ParamViewUserObject)((DefaultMutableTreeNode)value).getUserObject();
DefaultTreeCellRenderer nonLeaf = new DefaultTreeCellRenderer();
if(leaf||obj.isMo()){
TristateCheckBox checkBox = new TristateCheckBox(value.toString());
checkBox.setOpaque(false);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
checkBox.setState(((TristateCheckBox.State) hm.get(node)));
return checkBox;
}else{
return nonLeaf.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
}
}
}
}
三态树类
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ActionMapUIResource;
public class TristateCheckBox extends JCheckBox {
/**
*
*/
private static final long serialVersionUID = 1L;
/** This is a type-safe enumerated type */
public static class State {
private State() {}
}
public static final State NOT_SELECTED = new State();
public static final State SELECTED = new State();
public static final State DONT_CARE = new State();
private final TristateDecorator model;
public TristateCheckBox(String text, Icon icon, State initial) {
super(text, icon);
// Add a listener for when the mouse is pressed
super.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
grabFocus();
model.nextState();
}
});
// Reset the keyboard action map
ActionMap map = new ActionMapUIResource();
map.put("pressed", new AbstractAction() {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
grabFocus();
model.nextState();
}
});
map.put("released", null);
SwingUtilities.replaceUIActionMap(this, map);
// set the model to the adapted model
model = new TristateDecorator(getModel());
setModel(model);
setState(initial);
}
public TristateCheckBox(String text, State initial) {
this(text, null, initial);
}
public TristateCheckBox(String text) {
this(text, DONT_CARE);
}
public TristateCheckBox() {
this(null);
}
/** No one may add mouse listeners, not even Swing! */
public void addMouseListener(MouseListener l) {}
/**
* Set the new state to either SELECTED, NOT_SELECTED or
* DONT_CARE. If state == null, it is treated as DONT_CARE.
*/
public void setState(State state) {
model.setState(state);
}
/** Return the current state, which is determined by the
* selection status of the model. */
public State getState() {
return model.getState();
}
public void setSelected(boolean b) {
if (b) {
setState(SELECTED);
} else {
setState(NOT_SELECTED);
}
}
/**
* Exactly which Design Pattern is this? Is it an Adapter,
* a Proxy or a Decorator? In this case, my vote lies with the
* Decorator, because we are extending functionality and
* "decorating" the original model with a more powerful model.
*/
private class TristateDecorator implements ButtonModel {
private final ButtonModel other;
private TristateDecorator(ButtonModel other) {
this.other = other;
}
private void setState(State state) {
if (state == NOT_SELECTED) {
other.setArmed(false);
setPressed(false);
setSelected(false);
} else if (state == SELECTED) {
other.setArmed(false);
setPressed(false);
setSelected(true);
} else { // either "null" or DONT_CARE
other.setArmed(true);
setPressed(true);
setSelected(true);
}
}
/**
* The current state is embedded in the selection / armed
* state of the model.
*
* We return the SELECTED state when the checkbox is selected
* but not armed, DONT_CARE state when the checkbox is
* selected and armed (grey) and NOT_SELECTED when the
* checkbox is deselected.
*/
private State getState() {
if (isSelected() && !isArmed()) {
// normal black tick
return SELECTED;
} else if (isSelected() && isArmed()) {
// don't care grey tick
return DONT_CARE;
} else {
// normal deselected
return NOT_SELECTED;
}
}
/** We rotate between NOT_SELECTED, SELECTED and DONT_CARE.*/
private void nextState() {
State current = getState();
if (current == NOT_SELECTED) {
setState(SELECTED);
} else if (current == SELECTED) {
setState(DONT_CARE);
} else if (current == DONT_CARE) {
setState(NOT_SELECTED);
}
}
/** Filter: No one may change the armed status except us. */
public void setArmed(boolean b) {
}
/** We disable focusing on the component when it is not
* enabled. */
public void setEnabled(boolean b) {
setFocusable(b);
other.setEnabled(b);
}
/** All these methods simply delegate to the "other" model
* that is being decorated. */
public boolean isArmed() {
return other.isArmed();
}
public boolean isSelected() {
return other.isSelected();
}
public boolean isEnabled() {
return other.isEnabled();
}
public boolean isPressed() {
return other.isPressed();
}
public boolean isRollover() {
return other.isRollover();
}
public void setSelected(boolean b) {
other.setSelected(b);
}
public void setPressed(boolean b) {
other.setPressed(b);
}
public void setRollover(boolean b) {
other.setRollover(b);
}
public void setMnemonic(int key) {
other.setMnemonic(key);
}
public int getMnemonic() {
return other.getMnemonic();
}
public void setActionCommand(String s) {
other.setActionCommand(s);
}
public String getActionCommand() {
return other.getActionCommand();
}
public void setGroup(ButtonGroup group) {
other.setGroup(group);
}
public void addActionListener(ActionListener l) {
other.addActionListener(l);
}
public void removeActionListener(ActionListener l) {
other.removeActionListener(l);
}
public void addItemListener(ItemListener l) {
other.addItemListener(l);
}
public void removeItemListener(ItemListener l) {
other.removeItemListener(l);
}
public void addChangeListener(ChangeListener l) {
other.addChangeListener(l);
}
public void removeChangeListener(ChangeListener l) {
other.removeChangeListener(l);
}
public Object[] getSelectedObjects() {
return other.getSelectedObjects();
}
}
}
- Swing树结构节点渲染JCheckbox
- Swing之JTree篇:在树节点前增加JCheckBox控件
- java swing jbutton jradiobutton jcheckbox
- swing学习笔记十四(复选框JCheckBox )
- 7、java swing 添加 jcheckbox复选框
- java swing 复选JCheckBox组件美化
- JCheckBox
- Swing笔记(二)——JRadioButton和JCheckbox
- Java Swing界面编程(28)---复选框:JCheckBox
- Java Swing界面编程(29)---JCheckBox事件处理
- java swing 树型结构
- 节点包含checkbox的Swing树控件
- 节点包含checkbox的Swing树控件
- 渲染器与swing
- swing table渲染
- 文字渲染及渲染节点
- java swing 树结构代码
- java JTree JCheckBox 树复选框
- 显卡性能区分
- ensureCapacity()方法提高ArrayList的初始化速度
- bfs小结(持续更新中)
- CentOS安装播放视频软件mplayer
- SVC入门知识和JSVM基础实验
- Swing树结构节点渲染JCheckbox
- Android android下的短信发送器
- 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)
- Spring MVC开发web project笔记
- ADF Mobile-001:环境配置
- android中ListView的分页加载数据实现
- mplayer编译过程
- 技术人员为什么要写博客
- java中使用正则表达式