package com.test;
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 {
static final  long serialVersionUID =0;

/** This is a type-safe enumerated type */
public static class State
{
    private State() {}
}

public final        State NOT_SELECTED = new State();   
public final        State SELECTED     = new State();
public final static 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);
}

// Constractor types:
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(false);
        }
    }
    /**
     * 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 int     getMnemonic()                          {return other.getMnemonic(); }
    public String  getActionCommand()                     {return other.getActionCommand();}
    public Object[]getSelectedObjects()                   {return other.getSelectedObjects();}
    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 void    setActionCommand(String s)             {other.setActionCommand(s);}                      
    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);}      

}
}
最近下载更多
sckj_01  LV1 2023年5月2日
512816870  LV2 2022年9月8日
hg2370634854  LV2 2022年4月11日
antiwise  LV1 2022年1月10日
the_teenagers  LV1 2021年7月20日
有人ʰ 2021年7月15日
暂无贡献等级
zxc12188  LV1 2021年6月15日
zhu9527  LV2 2021年5月31日
李先生很好。  LV1 2021年3月27日
lizhenlinok  LV10 2021年1月11日
最近浏览更多
lcsking 昨天
暂无贡献等级
754210352  LV1 3月26日
辰槿de星星  LV2 2023年11月10日
漫步的海星  LV4 2023年8月28日
sckj_01  LV1 2023年5月2日
512816870  LV2 2022年9月8日
hg2370634854  LV2 2022年4月11日
微信网友_5852742079762432  LV6 2022年3月5日
一起吹过晚风的街  LV1 2022年1月17日
antiwise  LV1 2022年1月10日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友