JOptionPane

De ChuWiki
(Redirigido desde «JOptionPane y diálogos modales»)


¿Qué es un JOptionPane?[editar]

Un JOptionPane es una ventana emergente de una aplicación java swing que se usa para mostrar notificaciones al usuario.

Un JOptionPane suele tener un título de ventana, un texto con el mensaje que se quiere mostrar al usuario, un icono que puede indicarle la gravedad del mensaje, opcionalmente algún tipo de formulario sencillo estilo caja de texto o JComboBox y una serie de botones para cerrar el JOptionPane, como Ok, Aceptar, Cancelar, Sí, No.

Los JOptionPane son ventanas modales. Esto quiere decir que hasta que el usuario no la cierre, no puede tocar las demás ventanas de la interface.

¿Qué opciones tiene un JOptionPane?[editar]

Las opciones que ofrece JOptionPane son:

  • Mostrar un mensaje informativo al usuario
  • Pedir una confirmación al usuario antes de realizar una operación
  • Pedir un dato rápido al usuario.

Si hablamos de métodos de JOptionPane, tiene el método general showOptionDialog() que vale para las tres opciones. En él debemos dar todos los detalles de la ventana. Es decir, texto, título, icono, botones que queremos, si hay que pedir algún dato al usuario, etc. Como este método tiene bastantes parámetros y es un poco engorroso de usar, JOptionPane nos ofrece métodos simplificados para las tres opciones básicas.

  • showMessageDialog() : Ventana emergente para mostrar una información al usuario. Puede ser simplemente una información, un aviso, un error, etc.
  • showConfirmDialog() : Ventana emergente para pedir confirmación al usuario con opciones como SI, NO, CANCELAR. Por ejemplo, si está seguro de querer borrar algún dato de base de datos.
  • showInputDialog() : Ventana emergente para pedir al usuario algún dato rápido, como un texto, una opción de un menú, un valor entero, etc.

Estos son los métodos para hacer ventanas emergentes. Existe el mismo juego de métodos con apellido "internal" para aplicaciones que usen JInternalFrame. El comportamiento es igual, pero en vez de ventana emergente, aparecería dentro del JInternalFrame.

Código Java de ejemplo de JOptionPane[editar]

Vamos a ver en este tutorial ejemplos con JOptionPane. En github puedes ver el código de estos ejemplos. Nos centraremos solo en ejemplos de ventanas emergentes, no haremos los de JInternalFrame, puesto que el comportamiento es igual.

JOptionPane.showOptionDialog()[editar]

Tenemos un método JOptionPane.showOptionDialog() que nos muestra la ventana más configurable de todas, en ella debemos definir todos los botones que lleva. De hecho, las demás ventanas disponibles con JOptionPane se construyen a partir de esta. Por ello, al método debemos pasarle muchos parámetros:

  • parentComponent: A partir de este componente, se intentará determinar cual es la ventana que debe hacer de padre del JOptionPane. JOptionPane nunca se irá visualmente detrás de su ventana padre, quedando oculto por esta. Como componente padre se puede pasar null, pero entonces no tendría ventana padre y JOptionPane podría quedar oculta detrás de otras ventanas de nuestra aplicación. Y siendo JOptionPane modal, esto es bastante poco usable, no podemos manejar el resto de la interface de usuario y no vemos la ventana que lo está bloqueando todo. Por ello, conviene pasar, por ejemplo, el botón desde el cual se lanza la acción que provoca que se visualice el JOptionPane. De esta manera, la ventana de aviso se visualizará sobre el botón y no se podrá ir detrás del mismo si hacemos click en otro sitio.
  • message: El mensaje a mostrar, habitualmente un String, aunque vale cualquier Object cuyo método toString() devuelva algo con sentido.
  • title: El título para la ventana.
  • optionType: Un entero indicando qué opciones queremos que tenga la ventana. Los posibles valores son las constantes definidas en JOptionPane: DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION, o OK_CANCEL_OPTION.
  • messageType: Un entero para indicar qué tipo de mensaje estamos mostrando. Este tipo servirá para que se determine qué icono mostrar. Los posibles valores son constantes definidas en JOptionPane: ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, o PLAIN_MESSAGE
  • icon: Un icono para mostrar. Si ponemos null, saldrá el icono adecuado según el parámetro messageType.
  • options: Un array de objects que determinan las posibles opciones. Si los objetos son componentes visuales, aparecerán tal cual como opciones. Si son String, el JOptionPane pondrá tantos botones como String. Si son cualquier otra cosa, se les tratará como String llamando al método toString(). Si se pasa null, saldrán los botones por defecto que se hayan indicado en optionType.
  • initialValue: Selección por defecto. Debe ser uno de los Object que hayamos pasado en el parámetro options. Se puede pasar null.

La llamada a JOptionPane.showOptionDialog() devuelve un entero que representa la opción que ha seleccionado el usuario. La primera de las opciones del array es la posición cero. Si se cierra la ventana con la cruz de la esquina superior derecha, el método devolverá -1.

Aquí un ejemplo de cómo llamar a este método

int seleccion = JOptionPane.showOptionDialog(
   unComponentePadre,
   "Seleccione opcion", 
   "Selector de opciones",
   JOptionPane.YES_NO_CANCEL_OPTION,
   JOptionPane.QUESTION_MESSAGE,
   unIcono,    // null para icono por defecto.
   new Object[] { "opcion 1", "opcion 2", "opcion 3" },   // null para YES, NO y CANCEL
   "opcion 1");

if (seleccion != -1)
   System.out.println("seleccionada opcion " + (seleccion + 1));

y la ventana que se obtiene con el código anterior

JOptionPane showOptionDialog()

JOptionPane.showInputDialog()[editar]

Tenemos varios métodos JOptionPane.showInputDialog() y la diferencia entre ellos es que tienen más o menos parámetros, según queramos aceptar o no las opciones por defecto. Los parámetros y sus significados son muy similares a los del método showOptionDialog(), pero hay una diferencia.

Si usamos los métodos que no tienen array de opciones, la ventana mostrará una caja de texto para que el usuario escriba la opción que desee (un texto libre). Si usamos un método que tenga un array de opciones, entonces aparecerá en la ventana un JComboBox en vez de una caja de texto, donde estarán las opciones que hemos pasado.

La llamada se quedará bloqueada hasta que el usuario introduzca el dato y pulse Aceptar, o hasta que pulse Cancelar. Si pulsa Aceptar el método showInputDialog() devuelve el dato introducido por el usuario. Si pulsa Cancelar el método showInputDialog() devuelve null.

Aquí un par de trozos de código, el primero para conseguir una caja de texto,

// Con caja de texto
String seleccion = JOptionPane.showInputDialog(
   unComponentePadre,
   "Input dialog",
   JOptionPane.QUESTION_MESSAGE);  // el icono sera un iterrogante
        
// Si seleccion es null es que el usuario ha pulsado Cancelar.
System.out.println("El usuario ha escrito "+seleccion);

y la imagen que obtenemos con este código

JOptionPane showInputDialog()

En este segundo ejemplo, damos todas las opciones que queremos, obteniendo un JComboBox

// Con JCombobox
Object seleccion = JOptionPane.showInputDialog(
   unComponentePadre,
   "Seleccione opcion",
   "Selector de opciones",
   JOptionPane.QUESTION_MESSAGE,
   unIcono,  // null para icono defecto
   new Object[] { "opcion 1", "opcion 2", "opcion 3" }, 
   "opcion 1");

// Si selección en null es que el usuario ha cancelado el JOptionPane
System.out.println("El usuario ha elegido "+seleccion);

y esta es la imagen que se obtiene.

JOptionPane showInputDialog()

JOptionPane.showMessageDialog()[editar]

Esta es la más sencilla de todas, sólo muestra una ventana de aviso al usuario. La ejecución se detiene hasta que el usuario cierra la ventana. Hay varios métodos con el mismo nombre y más o menos parámetros, en función de si aceptamos las opciones por defecto (icono, por ejemplo) o queremos cambiar alguna cosa. Un trozo de código para llamarlo

JOptionPane.showMessageDialog(
   componentePadre,
   "Un aviso");

System.out.println("ya estas avisado");

y la imagen que muestra este código

JOptionPane showMessageDialog()

JOptionPane.showConfirmDialog()[editar]

Este método muestra una ventana pidiendo una confirmación al usuario, estilo "¿Seguro que lo quieres borrar todo?" y da al usuario opción de aceptar o cancelar ese borrado masivo que está a punto de hacer. El método devuelve un entero indicando la respuesta del usuario. Los valores de ese entero puede ser alguna de las constantes definidas en JOptionPane: YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, CLOSED_OPTION. Por supuesto, hay metodos iguales con más o menos parámetros para configurar las cosas más o menos.

El siguiente ejemplo de codigo

int confirmado = JOptionPane.showConfirmDialog(
   componentePadre,
   "¿Lo confirmas?");

if (JOptionPane.OK_OPTION == confirmado)
   System.out.println("confirmado");
else
   System.out.println("vale... no borro nada...");

muestra la siguiente imagen

JOptionPane showConfirmDialog()

Instanciar JOptionPane y obtener el JDialog[editar]

Hasta ahora hemos usado los métodos estáticos de JOptionPane para mostrar el diálogo. Estos métodos son cómodos y nos servirán la mayoría de las veces, pero tienen el inconveniente de que no tenemos una referencia al JDialog de la ventana del JOptionPane. Esto puede limitarnos en ciertos casos en que necesitaríamos esa referencia. Por ejemplo, si queremos cerrar automáticamente el JOptionPane desde código pasado un tiempo o si queremos cambiar el estilo de dicho JDialog antes de visualizarlo.

Para casos como este, hay otra opción para visualizar un JOptionPane. Los pasos son:

  1. Instanciar y configurar JOptionPane
  2. Obtener el JDialog del JOptionPane
  3. Hacer con el JDialog lo que necesitemos hacer (poner un timeout para cerrarlo, cambiarle colores de background o lo que sea).
  4. Visualizar el JDialog
  5. Analizar los datos devueltos en caso de que sea una entrada de datos.

Veamos código

// Se instancia y configura JOptionPane
JOptionPane optionPane = new JOptionPane("Mensaje a mostrar",
   JOptionPane.QUESTION_MESSAGE);
optionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);

// Estos solo son necesarios si queremos que JOptionPane sea de entrada de dato.
optionPane.setWantsInput(true);
optionPane.setInitialValue("Soy el dato");

Hemos hecho un new de JOptionPane. En el constructor podemos pasarle configuración y también ha partir de métodos setter. Si queremos que el JOptionPane sea de entrada de datos, es importante llamar a optionPane.setWantsInput(true). Esto hará que muestre la caja de texto donde el usuario debe meter los datos.

Ahora toca obtener el JDialog y visualizarlo

JDialog dialog = option.createDialog(parent, "Título del diálogo");

// Hacer lo que necesitemos con dialog

dialog.setVisible(true);
dialog.dispose();

Con optionPane.createDialog() obtenemos el JDialog. Pasamos como parámetros un padre y el título del JDialog. Ya tenemos el JDialog que todavía no está visible, así que podemos hacer lo que necesitemos hacerle. Una vez hecho, lo visualizamos con setVisible(true). Al ser diálogo modal, esta llamada se quedará bloqueada hasta que alguien cierre el diálogo.

Una vez que continúe el código, es porque ya se ha cerrado el JDialog, así que podemos hacerle dispose() para liberar su memoria.

El siguiente paso y solo si hemos configurado el JOptionPane para entrada de datos, será ver qué ha introducido el usuario.

if (JOptionPane.UNINITIALIZED_VALUE.equals(optionPane.getInputValue())){
   System.out.println("El usuario ha cancelado la operacion");
} else {
   System.out.println("El usuario ha introducido " + optionPane.getInputValue());
}

optionPane.getInputValue() devuelve el dato introducido por el usuario. Si devuelve JOptionPane.UNINITIALIZED_VALUE, es que se ha cancelado la entrada de datos. Cualquier otro valor será lo que ha introducido el usuario, incluido "" si ha dejado la caja vacía.

Más sobre JOptionPane[editar]