2010-02-02 33 views
4

Dans Windows, il est possible d'afficher une JCheckbox grisée, pour montrer que la collection de données qu'elle représente n'a pas tous la même valeur.Puis-je utiliser JCheckbox pour afficher "état mixte"

Est-ce encore possible avec un JCheckBox? Comment je m'y prend? (En espérant qu'il ya un moyen de ne pas la remplacer)

Merci

+0

Juste un FYI - grisé signifie généralement désactivé dans la conception de l'interface utilisateur, et il pourrait être une confusion pour vos utilisateurs si vous l'utilisez pour signifier quelque chose d'autre. J'ai vu, dans le passé, les gens montrer la case à cocher dans l'un des deux états (soit sélectionné ou désélectionné) quand il y a un état mixte, et laisser à l'utilisateur de déterminer s'il doit être sélectionné ou non. – aperkins

Répondre

0

Mon collègue à qui cette question est venue en pensait;

  1. Créez une JCheckBox fictive qui est désactivée et sélectionnée. définir la même taille que le vrai.
  2. Créez une icône qui peint la méthode réellement peint le JCheckbox factice.
  3. Définissez l'icône JCheckBox d'origine sur celle représentant le mannequin.
  4. Supprimer l'icône dès que JCheckBox est cliqué.

++ Pas surchargée JCheckBox

- pas un vrai tri-state Combo

Je pense qu'il est satisfait. Merci pour l'aide

1

Il est possible avec un peu de travail.

J'ai ce code depuis quelques années. Est basé à quelques exemples que j'ai trouvé dans Internet, mais je ne peux trouver aucune référence au créateur original, je me excuse si

import javax.swing.*; 
import javax.swing.event.ChangeListener; 
import javax.swing.plaf.ActionMapUIResource; 
import java.awt.event.*; 

/** 
* Maintenance tip - There were some tricks to getting this code 
* working: 
* 
* 1. You have to overwite addMouseListener() to do nothing 
* 2. You have to add a mouse event on mousePressed by calling 
* super.addMouseListener() 
* 3. You have to replace the UIActionMap for the keyboard event 
* "pressed" with your own one. 
* 4. You have to remove the UIActionMap for the keyboard event 
* "released". 
* 5. You have to grab focus when the next state is entered, 
* otherwise clicking on the component won't get the focus. 
* 6. You have to make a TristateDecorator as a button model that 
* wraps the original button model and does state management. 
*/ 
public class TristateCheckBox extends JCheckBox { 
    /** 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() { 
     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(); 
    } 
    } 
} 
+0

Merci pour l'effort! Mais je cherche un moyen de ne pas le contourner. Désolé de ne pas le mentionner – Houtman

+0

Le 'JCheckBox' normal ne peut pas le faire. Vous devez lancer le vôtre et étendre JCheckBox est le moyen le plus simple de le faire. – Bombe