Personalizar JOptionPane Java
Tienes todo el código de estos ejemplos en github, en el paquete joptionpane. El main está en JOptionPaneExamples.java
¿Cómo personalizar los botones de JOptionPane?[editar]
Todos los métodos de javax.swing.JOptionPane tienen un parámetro optionType al que podemos pasar algunos de estos valores:
- JOptionPane.DEFAULT_OPTION
- JOptionPane.YES_NO_OPTION
- JOptionPane.YES_NO_CANCEL_OPTION
- JOptionPane.OK_CANCEL_OPTION
Poniendo alguna de estas opciones podemos elegir qué juego de botones queremos que salgan en nuestro JOptionPane.
No obstante, puede que necesitemos un juego de botones totalmente distinto. Debemos usar entonces el método showOptionDialog(), que tiene todos los parámetros que se muestran a continuación
JOptionPane.showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue)
El penúltimo parámetro, options, es el que nos permite poner los botones que queramos. Si pasamos un array de String, cada String se representará como un botón. El último parámetro, initialValue, debe coincidir con uno de los String que pasemos en options. Será el botón que aparezca remarcado como opción por defecto.
Y no necesariamente tienen que ser String. Podemos poner cualquier objeto Java.
- Si los objetos que pasamos son componentes de javax.swing, se presentarán tal cual. Por ejemplo, podríamos pasar botones con los típicos iconos de aceptar/cancelar.
- Si no son componentes de javax.swing, se preesntarán botones cuya etiqueta sea el resultado de llamar a toString() de los objetos que pasemos.
Si es JOptionPane el que crea los botones (porque le pasamos objetos que no son componentes de javax.swing), la pulsación de cualquiera de los botones cerrará la ventana y el método showOptionDialog() nos devulve un entero que la posición dentro de options que ha sido la pulsada por el usuario.
Veamos un ejemplo
JTextField textField = new JTextField(30);
int buttonPressed = JOptionPane.showOptionDialog(parent, textField, "The title",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null,
new String[]{"Button 0", "Button 1", "Button 2", "Button 3", "Button 4"}, "Button 3");
System.out.println("Boton Pulsado " + buttonPressed);
Esto mostrará la siguiente ventana
Vemos la ristra de botones, numerados del 0 al 4. Vemos que el 3 es el que está marcado como opción por defecto. Si pulsamos cualquiera de ellos, veremos que la ventana se cierra y que en pantalla (System.out.println()) sale el índice del botón pulsado dentro del array de String.
Un detalle. Como segundo parámetro hemos pasado un JTextField. Esto es porque queremos que la ventana sea de entrada de datos. Si hubieramos puesto un String en vez de un textField, la ventana sería un mensaje. En el caso del textField, tendremos que encargarnos nosotros de leerlo según el significado que hayamos dado a los botones que se han creado. También se podrían usar los botones como datos a elegir, por ejemplo, si el JOptionPane es para elegir un color, el array de String podría ser {"Rojo", "Verde", "Azul"} y la simple pulsación del botón cerraría la ventana y nos devolvería el color elegido (la posición dentro de ese array).
Otro detalle. Como hemos pasado el parámetro options con valor, no null, entonces se ignora el parámetro JOptionPane.YES_NO_OPTION. Si hubieramos pasado null como opciones, se mostrarían esos botones YES/NO
Para poner botones personalizados en un JOptionPane podemos:
- Pasar un array de String u otros objetos Java como parámetro options
- Pasar un array de componentes javax.swing como parámetro options
¿Cómo dar formato al texto de JOptionPane?[editar]
Si en JOptionPane mostramos un mensaje de texto, sale en negrita, con una fuente determinada, una sola línea. Tenemos varias opciones para modificar el estilo de este texto.
- Admite caracteres \n en el texto para partir la línea
- Admite formato html
- Podemos poner un JLabel como texto del mensaje y ese JLabel lo podemos personalizar totalmente.
¿Cómo mostrar varias líneas de texto en JOptionPane?[editar]
Usando \n podemos hacerlo fácilmente
JOptionPane.showMessageDialog(parent, "Esta linea\nesta partida\nen tres");
que daría lugar a la siguiente imagen
¿Cómo cambiar estilo de texto en JOptionPane?[editar]
También admite html, por ejemplo, podemos poner varias líneas y cursiva
JOptionPane.showMessageDialog(parent, "<html>Todo esta en <b>negrita</b><br>Pero podemos poner <i>cursiva</i></html>");
que daría lugar a la siguiente imagen
La negrita no se nota, porque todo el texto está en negrita. Vemos el salto de línea y vemos la cursiva
¿Cómo Cambiar el color del texto en JOptionPane?[editar]
Finalmente, la opción de pasar un JLabel personalizado como mensaje.
final JLabel label = new JLabel("<html>Esta tiene <b>negrita</b><br>y <i>cursiva</i><br>y hemos personalizado la fuente</html>");
label.setFont(new Font("Arial", Font.PLAIN, 12));
label.setOpaque(true); // solo es necesario si queremos cambiar también el color de background. Por defecto, un JLabel es transparente.
label.setForeground(Color.RED);
JOptionPane.showMessageDialog(parent, label);
Hemos creado el JLabel con un texto, que también admite html, hemos cambiado la fuente, el color y el resultado es el siguiente
Para cambiar el estilo del texto de un JOptionPane podemos:
- Usar \n para partir en varias lineas.
- Usar texto html
- Poner un JLabel con el estilo que queramos
¿Cómo cambiar el icono de JOptionPane?[editar]
Se puede elegir entre los iconos por defecto de JOptionPane con el parémetro messageType, que puede tomar los siguiente valores:
- JOptionPane.ERROR_MESSAGE
- JOptionPane.INFORMATION_MESSAGE
- JOptionPane.WARNING_MESSAGE
- JOptionPane.QUESTION_MESSAGE
- JOptionPane.PLAIN_MESSAGE
Según el tipo de mensaje, se elegirá un icono de los de defecto: interrogantep, una i de información, etc.
Si no nos gusta ninguno de esos iconos o simplemente queremos otro, se puede pasar el parémetro icon con el Icon que queramos. Veamos el ejemplo
JOptionPane.showConfirmDialog(parent, "¿Quieres guardar el fichero?", "Salvar Fichero",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
new ImageIcon("src/main/files/Actions-document-save-icon.png"));
Como último parámetro hemos pasado un icono generado a partir de un fichero. El resultado es el de la siguiente imagen
Para cambiar el icono de un JOptionPane podemos:
- Elegir uno de los juegos de iconos por defecto con el parámetro messageType
- Pasar un icono como parámetro icon
solo queda elegir un icono más bonito :)
¿Cómo cambiar el color de background de un JOptionPane?[editar]
Cambiar el color de background de un JOptionPane no es difícil, pero tampoco es inmediato. Los motivos son dos
- Los métodos de JOptionPane muestran directamente la caja de diálogo, pero no tenemos la instancia de dicha caja de diálogo en ningún sitio donde podamos cambiar el color.
- Aunque la tuvieramos, el diálogo está compuesto por varios componentes anidados (el icono, los botones, el texto, etc). Una llamada a setBackground() del componente principal del JOPtionPane no es recursiva y no va a cambiar el background de todos los componentes.
Así que tenemos que hacer las cosas de otra manera. Primero, un método útil para cambiar el background de toda una jerarquia de componentes. Puede ser este
/* Método static de una clase de nombre Util */
public static void setBackgroundColor (Component component, Color color){
component.setBackground(color);
if (component instanceof Container){
for (Component component1 : ((Container) component).getComponents()) {
setBackgroundColor(component1, color);
}
}
}
y tenemos que tener la instancia de JOptionpane antes de mostrarlo. No es complejo, primero hacemos un new de JOptionPane y lo configuramos como queramos
JOptionPane optionPane = new JOptionPane("¿Quieres guardar el fichero?",
JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION,
new ImageIcon("src/main/files/Actions-document-save-icon.png"));
Los parámetros del constructor son similares a los métodos a los que estamos acostumbrados. Y hay varios constructores con distinto número de parámetros, para poner solo hasta donde nos interese. El siguiente paso es obtener la caja de diálogo. Hay un método específico para eso
JDialog dialog = optionPane.createDialog(customButton, "Salvar fichero");
bien, ya tenemos el JDialog y todavía no es visible, ahora bastaría llamar al método que hicimos inicialmente de cambio de color y hacer el diálogo visible
// Util es la clase donde hemos metido el método de cambio de background
Util.setBackgroundColor(dialog, Color.LIGHT_GRAY);
dialog.setVisible(true);
La llamada a setVisible(true) nos deja bloqueados hasta que el usuario cierre el diálogo, exactamente igual que la llamada a los métodos showXXX() a los que estamos acostumbrados. El resultado es el de la siguiente imagen
Para cambiar el color de background de un JOptionPane tenemos que:
- Obtener la instancias de la caja de diálogo de JOptionPane.
- Cambiar, recursivamente, el color de background de todos sus componentes