Como cambiar los colores de un JComboBox en Java
Para cambiar los colores de un JComboBox
en Java necesitamos crear nuestra propia clase BasicComboBoxRenderer
y definir en ella los colores que querarmos.
Veamos los detalles con un ejemplo que tienes en JComboBoxRender.java. En ese ejemplo también se cambia el botón del JComboBox
, pero eso lo explicaremos en otro tutorial. Ignora todo lo relativo a MyArrow
. Cualquier duda sobre este tutorial o Java en general suelo atender en este foro de java, python y otros
Creamos nuestro propio BasicComboBoxRenderer
[editar]
Para crear nuestro BasicComboBoxRenderer
solo tenemos que crear una clase que herede de BasicComboBoxRenderer
y sobreescribir el método getListCellRendererComponent()
. Vamos a ello
public static class MyComboBoxRender extends BasicComboBoxRenderer {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
// Aquí definimos los colores que queramos.
}
}
BasicComboBoxRenderer
acaba heredando a su vez de un JLabel
que es el que se usará para pintar los items del JComboBox
desplegado. Ojo, es importante, sólo los items del JComboBox
desplegado, NO del item visible cuando el JComboBox
no está desplegado. Para el item visible cuando no está desplegado, Java tiene una lógica un poco extraña que vemos más abajo.
Cambiar los colores de los items desplegados[editar]
Vamos con la parte del menú desplegable del JComboBox
.
Si llamamos al método de la clase padre getListCellRendererComponent()
se hará una parte importante de nuestro trabajo. Se pondrán los colores por defecto para el item en la lista desplegada teniendo en cuenta si etá seleccionado, si no lo está, si tiene el foco, si no lo tiene, según su valor sea un texto o un icono. Así que es buena idea hacer esta llamada y luego cambiar los colores que queramos. En nuestro ejemplo, vamos a cambiar el color del texto y del fondo, teniendo en cuenta si está o no seleccionado.
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
// La llamada a super hace que coja los colores defecto según esté seleccionado, tenga foco, etc.
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
// Cambiamos color de fondo y letra del item del combo desplegado.
if (isSelected) {
this.setForeground(Color.BLUE);
this.setBackground(Color.WHITE);
} else {
this.setBackground(Color.YELLOW);
this.setForeground(Color.RED);
}
...
Hemos hecho la llamada a super.getListCellRendererComponent()
para tener parte del trabajo hecho.
Como hemos dicho que nuestra clase hereda de BasicComboBoxRenderer
que a su vez acaba heredando a su vez de un <codeJJLabel y que este es el que se usa para el pintado de los item desplegados, nos basta llamar a this.setForeground()
y this.setBackground()
para cambiar los colores. Lo estamos haciendo en función de si el item está o no seleccionado.
Cambiar los colores del item visible cuando no está desplegado[editar]
Como hemos comentado, el item visible cuando no está desplegado el JComboBox
tiene una lógica extraña. Si el JComboBox
tiene el foco o el combo está desplegado, se va a dibujar con los colores "selected" del JList
que nos pasan como parámetro. Así que tenemos que cambiar los colores "selected" de dicho JList
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
...
// list dibuja el elemento visible del combo cuando no está desplegado.
list.setSelectionBackground(Color.RED);
list.setSelectionForeground(Color.YELLOW);
return this;
}
Una vez cambiados los colores del JList
, solo nos queda devolver el JLabel
para pintando de los items. Como acabamos heredando de dicho JLabel
, basta poner un return this
al final.
Si el JComboBox
no tiene el foco o su menú está desplegado, el color del item sale con los colores por defecto del JComboBox
. Así que para este caso, no tener el foco o tener el menú desplegado, la forma de cambiarlo es cambiando los colores del JComboBox
directamente.
combo.setBackground(Color.RED);
combo.setForeground(Color.YELLOW);
Cambiar los colores cuando el JComboBox
está deshabilitado[editar]
No hay una forma fácil y elegante de cambiar los colores del JComboBox
cuando está deshabilitado. Esto se debe a que el código de java por debajo no contempla esta opción. Sin embargo, si existe una forma fácil no elegante. Consiste en hacer el JComboBox
editable para que presente un editor del combo. El editor es un JTextField
y no un JLable
. Aunque el combo sea editable, como está deshabilitado, no podremos tocar en él. Así que nos puede valer.
Simplemente tenemos que cambiar los colores del editor, sabiendo que por debajo es un JtextField
// Colores para cuando está deshabilitado
combo.getEditor().getEditorComponent().setBackground(Color.RED);
((JTextField)combo.getEditor().getEditorComponent()).setDisabledTextColor(Color.YELLOW);
Construir el JComboBox con el BasicComboBoxRenderer
[editar]
Ya solo nos queda construir el JComboBox
y ponerle todo lo que hemos construido
JComboBox<String> combo = new JComboBox<>();
// Cambiamos el render y los colores por defecto.
combo.setRenderer(new MyComboBoxRender());
combo.setBackground(Color.RED);
combo.setForeground(Color.YELLOW);
// Colores para cuando está deshabilitado. Para que haga caso, además de deshabilitar el combo,
// debemos ponerlo editable y acordarnos de ponerlo no editable cuando lo habilitemos.
combo.getEditor().getEditorComponent().setBackground(Color.RED);
((JTextField)combo.getEditor().getEditorComponent()).setDisabledTextColor(Color.YELLOW);
El resultado de este código completo es el de la siguiente imagen
Cambiar los colores del botón del JComboBox
[editar]
En este otro tutorial explicamos cómo cambiar los colores del botón del JComboBox
Cambiar los colores de todos los JComboBox
de la aplicación[editar]
Si queremos hacer esto con todos los JComboBox
de la aplicación, hay una forma más fácil, aunque tiene sus pegas. Consiste en cambiar los colores por defecto usando UIManager
. El código sería el siguiente
UIManager.put("ComboBox.background",Color.RED);
UIManager.put("ComboBox.foreground",Color.YELLOW);
UIManager.put("ComboBox.disabledForeground", Color.YELLOW);
UIManager.put("ComboBox.disabledBackground", Color.RED);
UIManager.put("ComboBox.selectionBackground", Color.WHITE);
UIManager.put("ComboBox.selectionForeground", Color.BLUE);
El problema con esto es qeu los colores ComboBox.selectionBackground
y ComboBox.selectionForeground
se usan tanto para el item seleccionado en el desplegable como para el valor visible cuando el desplegable está oculto y el JComboBox
está oculto. Cuando el JComboBox
pierda o gane el foco, veremos el cambio de color entre ComboBox.background
y ComboBox.selectionBackground
, así como en los "foreground" equivalentes.