2011-04-14 15 views
11

¿Es posible establecer un valor y una etiqueta en JComboBox para que pueda mostrar una etiqueta pero obtener un valor diferente?Etiqueta de configuración JComboBox y valor

Por ejemplo en JavaScript que puede hacer:

document.getElementById("myselect").options[0].value //accesses value attribute of 1st option 
document.getElementById("myselect").options[0].text //accesses text of 1st option 

Respuesta

1

Uso ListCellRenderer para lograr lo que quiere. Haga una clase que extienda JLabel e implemente ListCellRenderer. Establezca esa clase como un representador en su JComboBox utilizando el método setRenderer(). Ahora cuando accedes a los valores desde tu jcombobox, será de tipo jlabel.

+1

Esto funcionará, pero interrumpirá la navegación del teclado, que se basa en el toString de los elementos del combo. –

+0

@JB Nizet: entonces la navegación del teclado está rota ;-) El camino a seguir es solucionarlo en lugar de hacks sucios en toString – kleopatra

+0

@kleopatra: El código de navegación del teclado está profundamente oculto dentro de una clase interna no accesible de javax.swing .plaf.basic.BasicComboUI, y no hay manera fácil, aparte de volver a implementarlo y acoplarlo al renderizador, de anularlo. Estoy de acuerdo con su principio, pero el diseño de esta parte de Swing hace que sea muy doloroso seguir este principio. Creo que un objeto envoltorio genérico redefinir toString y delegar todo lo demás (es decir, hashCode) al objeto envuelto es una mejor solución. –

25

Puede colocar cualquier objeto dentro de un JComboBox. De manera predeterminada, usa el método toString del objeto para mostrar una etiqueta navegar en el cuadro combinado usando el teclado. Por lo tanto, la mejor manera es, probablemente, para definir y utilizar objetos apropiados dentro del combo:

public class ComboItem { 
    private String value; 
    private String label; 

    public ComboItem(String value, String label) { 
     this.value = value; 
     this.label = label; 
    } 

    public String getValue() { 
     return this.value; 
    } 

    public String getLabel() { 
     return this.label; 
    } 

    @Override 
    public String toString() { 
     return label; 
    } 
} 
+0

Por favor, ¿puede mostrarme un ejemplo completo? No entiendo cómo poner este objeto en un JComboBox ... – xdevel2000

+2

@ xdevel2000 Simplemente crea un array de estos objetos y configúralo en el cuadro combinado ComboItem [] items = new ComboItem [] {new ComboItem ("value1", "etiqueta1"), nuevo ComboItem ("valor2", "etiqueta2")}; JComboBox cb = new JComboBox (elementos); – Boro

+2

@kleopatra: ¿cómo haces cuando el toString de un objeto es "foo", y quieres que aparezca "bar" en el combo? Usar un renderizador funciona. Pero si presionas B en el combo, no selecciona nada. Y si presionas F en el combo, selecciona el elemento representado como "barra". Lo cual no es aceptable Es por eso que sugiero usar objetos wrapper que tengan un método toString adecuado. –

6

Por favor, me puede mostrar un ejemplo completo?

Las instancias de Enum son particularmente convenientes para esto, como toString() "devuelve el nombre de esta constante de enumeración, que figura en la declaración."

enter image description here

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** @see http://stackoverflow.com/questions/5661556 */ 
public class ColorCombo extends JPanel { 

    private Hue hue = Hue.values()[0]; 

    public ColorCombo() { 
     this.setPreferredSize(new Dimension(320, 240)); 
     this.setBackground(hue.getColor()); 
     final JComboBox colorBox = new JComboBox(); 
     for (Hue h : Hue.values()) { 
      colorBox.addItem(h); 
     } 
     colorBox.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       Hue h = (Hue) colorBox.getSelectedItem(); 
       ColorCombo.this.setBackground(h.getColor()); 
      } 
     }); 
     this.add(colorBox); 
    } 

    private enum Hue { 

     Cyan(Color.cyan), Magenta(Color.magenta), Yellow(Color.yellow), 
     Red(Color.red), Green(Color.green), Blue(Color.blue); 

     private final Color color; 

     private Hue(Color color) { 
      this.color = color; 
     } 

     public Color getColor() { 
      return color; 
     } 
    } 

    private static void display() { 
     JFrame f = new JFrame("Color"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new ColorCombo()); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       display(); 
      } 
     }); 
    } 
} 
8

Aquí es una interfaz de servicios públicos y de clase que hacen que sea fácil obtener un cuadro combinado para utilizar diferentes etiquetas. En lugar de crear un reemplazo ListCellRenderer (y arriesgarse a que parezca fuera de lugar si se cambia la apariencia), este usa el valor predeterminado ListCellRenderer (cualquiera que sea), pero intercambiando sus propias cadenas como texto de etiqueta en lugar de las que definido por toString() en sus objetos de valor.

public interface ToString { 
    public String toString(Object object); 
} 

public final class ToStringListCellRenderer implements ListCellRenderer { 
    private final ListCellRenderer originalRenderer; 
    private final ToString toString; 

    public ToStringListCellRenderer(final ListCellRenderer originalRenderer, 
      final ToString toString) { 
     this.originalRenderer = originalRenderer; 
     this.toString = toString; 
    } 

    public Component getListCellRendererComponent(final JList list, 
      final Object value, final int index, final boolean isSelected, 
      final boolean cellHasFocus) { 
     return originalRenderer.getListCellRendererComponent(list, 
      toString.toString(value), index, isSelected, cellHasFocus); 
    } 

} 

Como se puede ver la ToStringListCellRenderer para crear una cadena personalizada de la aplicación ToString, y luego lo pasa a la original ListCellRenderer en lugar de pasar en el valor propio objeto.

Para utilizar este código, hacer algo como lo siguiente:

// Create your combo box as normal, passing in the array of values. 
final JComboBox combo = new JComboBox(values); 
final ToString toString = new ToString() { 
    public String toString(final Object object) { 
     final YourValue value = (YourValue) object; 
     // Of course you'd make your own label text below. 
     return "custom label text " + value.toString(); 
    } 
}; 
combo.setRenderer(new ToStringListCellRenderer(
     combo.getRenderer(), toString))); 

Además de utilizar esto para hacer etiquetas personalizadas, si realiza una implementación ToString que crea cadenas en base a la configuración regional del sistema, puede fácilmente internacionalice el cuadro combinado sin tener que cambiar nada en sus objetos de valor.

+0

OK, pero el método toString de ToString toString final se invoca cada vez que paso el comboBox con el mouse. ¿Cómo reduzco la cantidad de llamadas? – Blocked