2009-08-11 33 views
11

Realmente podría usar una casilla de verificación tri declarada en Java. Suena como algo simple, pero solo he visto realmente ugly implementations [nota: el enlace ahora está roto].Casillas de verificación Tristate en Java

Tres botones de opción ocupan demasiado espacio y probablemente sean confusos para los usuarios en mi caso. Básicamente es para un diálogo de búsqueda. Necesito opciones verdaderas, falsas o "no me importa". ¿Hay alguna técnica diferente que las personas usen?

Respuesta

5

He encontrado una manera de hacer una casilla de verificación de los tres estados con sólo añadir un oyente:


public class TriStateActionListener implements ActionListener{ 
    final protected Icon icon; 

    public TriStateActionListener(Icon icon){ 
     this.icon=icon; 
    } 

    public static Boolean getState(javax.swing.JCheckBox cb){ 
     if (cb.getIcon()==null) return null; 
     if (cb.isSelected()) return true; 
     else return false; 
    } 

    public void actionPerformed(ActionEvent e) { 
     javax.swing.JCheckBox cb=(javax.swing.JCheckBox)e.getSource(); 
     if (!cb.isSelected()){ 
      cb.setIcon(icon); 
     } 
     else if (cb.getIcon()!=null){ 
      cb.setIcon(null); 
      cb.setSelected(false); 
     } 
    } 
} 

Luego, en el código de la aplicación, es sólo una sola línea:


jCheckBox1.addActionListener(new TriStateActionListener(getResourceMap().getIcon("TriStateIcon"))); 

Después de todo el retroalimentación, estoy pensando que un menú desplegable puede ser una mejor opción. Pero, quería compartir mi código aquí para todos los demás.

14

Use un menú desplegable.

+1

1 buena idea. si un componente de la interfaz de usuario es difícil de codificar y no estándar, también se sentirá así para el usuario. ¿Cuándo fue la última vez que usó una casilla de verificación tri-estado de esa manera? Yo nunca he. –

+8

Aunque estoy de acuerdo con el punto de @ byron, una casilla de verificación tri-estado es bastante estándar desde el punto de vista de un usuario. –

+5

¿Qué usuarios? Soy desarrollador y usuario avanzado, y desprecio las casillas de verificación de tres estados, generalmente porque no está claro qué significa el tercer estado; por lo general, significa que se te ocultan algunos detalles. Es una pesadilla de usabilidad y accesibilidad. – Rob

0

Solo usaría la que publicaste.

Mientras su complejidad esté en otra clase (que funcione) y actúe como cualquier otro control, ¿a quién le importa? (Esa parece ser la suposición detrás de todo el swing, la mayoría de las clases de swing parecen ser así de complicadas).

2

Eso "implementaciones feas" es un enlace antiguo. Una de las sugerencias en esa página se actualizó hace un par de años. No he probado la implementación anterior, así que no sé si la nueva es mejor o peor.

TristateCheckBox Revisited

+0

Sí, creo que Heinz Kabutz lo hizo muy bien. ¡Yo también lo recomendaría! – codevour

0

Cambiar la interfaz de usuario. La casilla de verificación Tristate es inusual y realmente puede confundir a los usuarios. El menú desplegable es una buena opción, pero para más de una ocurrencia dentro del cuadro de diálogo también traerá mucha confusión al usuario.

2

Las casillas de verificación de tres estados son expresiones UI estándar para las vistas de árbol con nodos de niños parcialmente comprobados. Se usan ampliamente en la gestión de capas en vistas jerárquicas complejas como Google Earth.

3

JIDE han abierto origen algunas funciones muy agradable en su Common Layer, uno de los cuales pasa a ser una casilla de verificación de tres estados

Tristate checkboxes

Yo sugeriría que usted va a ejecutar la webstart demo para ver si cumple con sus necesidades

4

enter image description here

En esta implementación los tres estado sólo puede ser establecido a través de programación. Para ser portátil, utiliza imágenes, que deben colocarse dentro del mismo paquete de Java.

enter image description here enter image description here enter image description here

public class TristateCheckBox extends JCheckBox { 

    private static final long serialVersionUID = 1L; 
    private boolean halfState; 
    private static Icon selected = new javax.swing.ImageIcon(TristateCheckBox.class.getResource("selected.png")); 
    private static Icon unselected = new javax.swing.ImageIcon(TristateCheckBox.class.getResource("unselected.png")); 
    private static Icon halfselected = new javax.swing.ImageIcon(TristateCheckBox.class.getResource("halfselected.png")); 

    @Override 
    public void paint(Graphics g) { 
     if (isSelected()) { 
      halfState = false; 
     } 
     setIcon(halfState ? halfselected : isSelected() ? selected : unselected); 
     super.paint(g); 
    } 

    public boolean isHalfSelected() { 
     return halfState; 
    } 

    public void setHalfSelected(boolean halfState) { 
     this.halfState = halfState; 
     if (halfState) { 
      setSelected(false); 
      repaint(); 
     } 
    } 
} 

marco de la muestra:

public class NewJFrame19 extends javax.swing.JFrame { 

    private final TristateCheckBox myCheckBox; 

    public NewJFrame19() { 
     myCheckBox = new TristateCheckBox(); 
     myCheckBox.setText("123123"); 
     add(myCheckBox); 

     jButton1 = new javax.swing.JButton(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     getContentPane().setLayout(new java.awt.FlowLayout()); 

     jButton1.setText("jButton1"); 
     jButton1.addActionListener(new java.awt.event.ActionListener() { 
      public void actionPerformed(java.awt.event.ActionEvent evt) { 
       jButton1ActionPerformed(evt); 
      } 
     }); 
     getContentPane().add(jButton1); 

     pack(); 
    } 

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
     myCheckBox.setHalfSelected(true); 
    }           

    public static void main(String args[]) { 

     try { 
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
       if ("Windows".equals(info.getName())) { 
        javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (ClassNotFoundException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame19.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (InstantiationException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame19.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (IllegalAccessException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame19.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } catch (javax.swing.UnsupportedLookAndFeelException ex) { 
      java.util.logging.Logger.getLogger(NewJFrame19.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } 
     /* Create and display the form */ 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       new NewJFrame19().setVisible(true); 
      } 
     }); 
    } 
    private javax.swing.JButton jButton1; 
} 
+1

Utilizamos este enfoque para una casilla que denota la agregación de estados de encendido/apagado. La interacción activa y desactiva todo, el estado intermedio solo se puede alcanzar a través de la interacción con los elementos individuales. Funciona muy bien y creo que es más sólido en términos de diseño de interfaz de usuario. –

3

No sé por qué alguien le daría a las soluciones con los archivos de icono adicional png mientras API Java da una gran funcionalidad para anulando método paintIcon (..).

La mejor solución liviana para recordar el estado de CheckBox es IMO ClientProperty atributo.

enter image description here

/* 
* Tri-state checkbox example 
* @s1w_ 
*/ 
import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 


class TCheckBox extends JCheckBox implements Icon, ActionListener { 

    final static boolean MIDasSELECTED = true; //consider mid-state as selected ? 


    public TCheckBox() { this(""); } 

    public TCheckBox(String text) { 
     super(text); 
     putClientProperty("SelectionState", 0); 
     setIcon(this); 
     addActionListener(this); 
    } 

    public TCheckBox(String text, int sel) { 
     /* tri-state checkbox has 3 selection states: 
     * 0 unselected 
     * 1 mid-state selection 
     * 2 fully selected 
     */ 
     super(text, sel > 1 ? true : false); 

     switch (sel) { 
      case 2: setSelected(true); 
      case 1: 
      case 0: 
       putClientProperty("SelectionState", sel); 
       break; 
      default: 
       throw new IllegalArgumentException(); 
     } 
     addActionListener(this); 
     setIcon(this); 
    } 

    @Override 
    public boolean isSelected() { 
     if (MIDasSELECTED && (getSelectionState() > 0)) return true; 
     else return super.isSelected(); 
    } 

    public int getSelectionState() { 
     return (getClientProperty("SelectionState") != null ? (int)getClientProperty("SelectionState") : 
             super.isSelected() ? 2 : 
             0); 
    } 

    public void setSelectionState(int sel) { 
     switch (sel) { 
      case 2: setSelected(true); 
        break; 
      case 1: 
      case 0: setSelected(false); 
        break; 
      default: throw new IllegalArgumentException(); 
     } 
     putClientProperty("SelectionState", sel); 
    } 


    final static Icon icon = UIManager.getIcon("CheckBox.icon"); 

    @Override 
    public void paintIcon(Component c, Graphics g, int x, int y) { 
     icon.paintIcon(c, g, x, y); 
     if (getSelectionState() != 1) return; 

     int w = getIconWidth(); 
     int h = getIconHeight(); 
     g.setColor(c.isEnabled() ? new Color(51, 51, 51) : new Color(122, 138, 153)); 
     g.fillRect(x+4, y+4, w-8, h-8); 

     if (!c.isEnabled()) return; 
     g.setColor(new Color(81, 81, 81)); 
     g.drawRect(x+4, y+4, w-9, h-9); 
    } 

    @Override 
    public int getIconWidth() { 
     return icon.getIconWidth(); 
    } 

    @Override 
    public int getIconHeight() { 
     return icon.getIconHeight(); 
    } 

    public void actionPerformed(ActionEvent e) { 
     TCheckBox tcb = (TCheckBox)e.getSource(); 
     if (tcb.getSelectionState() == 0) 
      tcb.setSelected(false); 

     tcb.putClientProperty("SelectionState", tcb.getSelectionState() == 2 ? 0 : 
                tcb.getSelectionState() + 1); 

     // test 
     System.out.println(">>>>IS SELECTED: "+tcb.isSelected()); 
     System.out.println(">>>>IN MID STATE: "+(tcb.getSelectionState()==1)); 
    } 
} 

uso: TCheckBox tcb = new TCheckBox("My CheckBox");

Cuestiones relacionadas