Beginning Sistemas de Información Java Diálogos Listado siguiente
PresentaciónEntrada/SalidaBibliotecasSwingMarcosBotonesCuadros de texto
ListasImágenesMenúsDiálogosArchivosGráficos 2D 

Cuadros de diálogo y mensajes de alerta
El uso de pequeñas ventanas auxiliares, bien sea para notificar al usuario o para solicitar informaciones puntuales, está sumamente extendido en todas las interfaces gráficas de usuario. Java ofrece dos componentes, JOptionPane y JDialog, destinados a satisfacer este tipo de necesidades. Veamos en primer lugar un pequeño ejemplo de cuadro de diálogo que solicita una información y verifica la validez de la respuesta.

Ejemplo.- Construir un programa que solicite un valor numérico entero cuyo valor esté entre entre 1 y 10. El programa deberá seguir solicitando el número mientras el valor de este no satisfaga estos requisitos. Una vez insertado un valor válido, el programa lo mostrará en pantalla con un tamaño mayor que el normal.

Una posible versión de este programa es la que puede verse en las imágenes siguientes:

El programa arranca con un marco centrado en pantalla, y sin visualizar número alguno. El menú archivo ofrece dos opciones, Ctrl-D para mostrar el cuadro de diálogo y Ctrl-Q para salir de programa. Obsérvese que esta ventana es un JFrame del tipo empleado habitualmente; no se ha utilizado todavía ningún JDialog.
En esta imagen se observa lo que ocurre cuando el usuario inserta una cadena alfanumérica en lugar de un número entero y pulsa Intro. El resultado es un pitido y el progama pasa a mostrar el contenido del cuadro de texto seleccionado en su totalidad, para facilitar la introducción de un nuevo valor. El programa permaecerá en esta situación mientras el usuario no inserte un número entero que satisfaga los requisitos impuestos.
Estas imágenes muestran lo que sucede cuando el usuario inserta un valor numérico correcto (el 7 en la imagen) y pulsa Intro. El programa admite el valor como válido, desaparece el cuadro de diálogo y pasa a mostrarse el valor introducido en la ventana principal del programa. Para activar el cuadro de diálogo se puede seleccionar la primera opción del menú Archivo, o se puede pulsar Ctrl-D.


El programa consta de los archivos siguientes: El contenido de estos archivos es el siguiente:
DemoInput.java
//
//  DemoInput.java
//

import javax.swing.*;
import java.awt.event.*;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Font;

public class DemoInput extends JFrame implements ActionListener {
    JDialog dialogo;
    
    JTextField cuadro;
    VerificadorCuadro verificador;
    
    JLabel resultado;
    
    JMenu archivo;
    JMenuBar jmb;
    JMenuItem salir, mostrar_dialogo;
    JButton cancelar, aceptar;
    
    DemoInput() {
    super("DemoInput");
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we)
            {
             System.exit(0);
             }});
        // Se prepara la barra de menús
        
        jmb = new JMenuBar();
        
        archivo = new JMenu("Archivo");
        salir = new JMenuItem("Salir");
        salir.addActionListener(new Finis());
        salir.setAccelerator(KeyStroke.getKeyStroke('Q',
	java.awt.Event.CTRL_MASK));
        mostrar_dialogo = new JMenuItem("Mostrar diálogo");
        mostrar_dialogo.addActionListener(this);
        mostrar_dialogo.setAccelerator(KeyStroke.getKeyStroke('D',
	java.awt.Event.CTRL_MASK));
        
        // Se añade un JLabel para mostrar el resultado
        resultado = new JLabel("***");
        resultado.setFont(new Font("Serif", Font.PLAIN, 72));
        resultado.setHorizontalAlignment(SwingConstants.CENTER);
        resultado.setPreferredSize(new Dimension(200,200));
        getContentPane().add(BorderLayout.CENTER, resultado);
        
        cancelar = new JButton("Cancelar");
        cancelar.addActionListener(this);
        aceptar = new JButton("Aceptar");
        aceptar.addActionListener(this);

        preparar_dialogo();
        
        
        archivo.add(mostrar_dialogo);
        archivo.add(salir);
        jmb.add(archivo);
        
        setJMenuBar(jmb);
        
    pack();
    setLocationRelativeTo(null);
    setVisible(true);
    }
    public void actionPerformed(ActionEvent e) {
        Object origen = e.getSource();
        if (origen==mostrar_dialogo)
            {
                dialogo.setVisible(true);
                cuadro.requestFocus();
            }
        else if (origen == cancelar)
            {
                dialogo.setVisible(false);
            }
        else if(origen == aceptar)
            {
                if (verificador.verify(cuadro))
                    {
                        resultado.setText(cuadro.getText());
                        dialogo.setVisible(false);
                    }
                else
                    Toolkit.getDefaultToolkit().beep();
            }
        else if(origen == cuadro)
            aceptar.doClick();
    }
    public void preparar_dialogo() {
        JPanel botones = new JPanel(new GridLayout(1,2));
        JPanel rotuloycuadro = new JPanel(new GridLayout(1,2));
        
        cuadro = new JTextField(10);
        verificador = new VerificadorCuadro();
        cuadro.setInputVerifier(verificador);
        cuadro.addActionListener(this);
        cuadro.setRequestFocusEnabled(true);
        
        rotuloycuadro.add(new JLabel(
        	"Escriba un número entero entre 1 y 10:"));
        rotuloycuadro.add(cuadro);
        
        
        botones.add(cancelar);
        botones.add(aceptar);
        
        dialogo = new JDialog(this, "Ejemplo de verificación",
  false);
        dialogo.getContentPane().add(BorderLayout.NORTH,
        rotuloycuadro);
        dialogo.getContentPane().add(BorderLayout.SOUTH,
        botones);
        dialogo.pack();
        dialogo.setLocationRelativeTo(this);
   }
    
    public static void main(String args[]) {
 new DemoInput();
    }
}

Finis.java
import java.awt.event.ActionListener;

import java.awt.event.ActionEvent;



public class Finis implements ActionListener {

 public void actionPerformed(ActionEvent e) {

  System.exit(0);

 }

}


VerificadorCuadro.java
//
//  VerificadorCuadro.java
//  DemoInput
//

import javax.swing.*;
import java.awt.Toolkit;

public class VerificadorCuadro extends InputVerifier {
    public boolean verify(JComponent jc) {
        JTextField campo = (JTextField)jc;
        String contenido = campo.getText();
        boolean numero_valido, valor_valido, resultado_final;
        int numero = 0;
        numero_valido = true;
        valor_valido = true;
        try
            {
                numero = Integer.parseInt(contenido);
            }
        catch(Exception e)
            {
                numero_valido = false;
            }
        valor_valido = (numero>0 && numero<11);
        resultado_final = numero_valido && valor_valido;
        if (!resultado_final)
         {
            campo.selectAll();
     }
        return resultado_final;
    }
}



Comentarios.- Este programa ilustra el concepto de validación de información, junto con el uso elemental de un cuadro de diálogo. Como puede verse, su manejo es bastante análogo al de un JFrame.

Como ya se ha indicado en otras ocasiones, una forma cómoda de trabajar consiste en crear un makefile y un manifest para crear directamente el archivo .jar que contiene todo el progrmama. Estos archivos podrían ser como sigue:

makefile
CLASSES = DemoInput.class Finis.class VerificadorCuadro.class 
program.jar: $(CLASSES)
	jar cmf manifest program.jar *.class

DemoInput.class: DemoInput.java
	javac DemoInput.java

Finis.class: Finis.java
	javac Finis.java

VerificadorCuadro.class: VerificadorCuadro.java
	javac VerificadorCuadro.java

clean:
	rm -f *.class
	rm -f *.jar

manifest
Main-Class: DemoInput



Este makefile funciona correctamente en Unix. El archivo .jar creado se llama program.jar y la clase principal, claro, es DemoInput. Los resultados de ejecutar el programa son los que se han mostrado en la parte superior de la página.

Cuadros de diálogo "prefabricados"
El lector interesado en construir pequeños cuadros de diálogo para mostrar pequeñas informaciones o peticiones al usuario debe consultar la documentación relativa a JOptionPane. Véase a continuación un pequeño ejemplo que muestra distintos tipos de cuadros de diálogo obtenidos de forma muy sencilla. La lista de archivos que intervienen en el programa es la siguiente: Véase a continuación el contenido de los distintos archivos.
AccionConfirmacion.java
//
//  AccionConfirmacion.java
//  DemoDialogos
//

import java.awt.event.*;
import javax.swing.*;

public class AccionConfirmacion implements ActionListener {
 JLabel jl;
 String[] respuestas = {"YES_OPTION", "NO_OPTION",
 "CANCEL_OPTION", "OK_OPTION", "CLOSED_OPTION"};
 AccionConfirmacion(JLabel jl) {
  this.jl = jl;
 }
 public void actionPerformed(ActionEvent e) {
  int opcion = Integer.parseInt(e.getActionCommand());
  int resultado = 0;
  switch(opcion) {
   case 0: resultado = JOptionPane.showConfirmDialog( jl,
             "Diga que si",
             "Muestra opción predeterminada",
             JOptionPane.DEFAULT_OPTION);
     break;
   case 1: resultado = JOptionPane.showConfirmDialog( null,
             "Diga si o no",
             "Muestra opción Si/No",
             JOptionPane.YES_NO_OPTION);
     break;
   case 2: resultado = JOptionPane.showConfirmDialog( null,
             "Diga si, no o cancelar",
             "Muestra opción Si/No/Cancelar",
             JOptionPane.YES_NO_CANCEL_OPTION);
     break;
   case 3: resultado = JOptionPane.showConfirmDialog( null,
             "Confirme, por favor",
             "Solicitud de confirmación",
             JOptionPane.OK_CANCEL_OPTION);
       break;
  }// switch
  jl.setText("Se ha pulsado la opción "
   + respuestas[resultado]);
 }
}

AccionEntrada.java
//
//  AccionEntrada.java
//  DemoDialogos
//

import java.awt.event.*;
import javax.swing.*;

public class AccionEntrada implements ActionListener {
 JLabel jl;
 AccionEntrada(JLabel jl) {
  this.jl = jl;
 }
 public void actionPerformed(ActionEvent e) {
  int opcion = Integer.parseInt(e.getActionCommand());
  String resultado = null;
  switch(opcion) {
   case 0: resultado
    = JOptionPane.showInputDialog("Escriba una cadena:");
     break;
   case 1: String[] pos = {"Alfa", "Beta", "Delta", "Gamma"};
     resultado = (String)JOptionPane.showInputDialog( null,
             "Seleccione una:",
             "Lista de posibles elecciones",
             JOptionPane.INFORMATION_MESSAGE,
             null,
             pos,
             pos[0]);
     break;
  }// switch
  jl.setText("El resultado es " 
   + (resultado==null?"Cancelado":resultado));
 }
}

AccionMensajes.java
//
//  AccionMensajes.java
//  DemoDialogos
//

import java.awt.event.*;
import javax.swing.*;

public class AccionMensajes implements ActionListener {
 JLabel jl;
 AccionMensajes(JLabel jl) {
  this.jl = jl;
 }
 public void actionPerformed(ActionEvent e) {
  int opcion = Integer.parseInt(e.getActionCommand());
  int resultado;
  switch(opcion) {
   case 0: JOptionPane.showMessageDialog( jl,
           "Este es el mensaje",
           "Este es el título",
           JOptionPane.ERROR_MESSAGE);
       break;
   case 1: JOptionPane.showMessageDialog( null,
                       "Información",
                       "Mensaje de información",
                       JOptionPane.INFORMATION_MESSAGE);
       break;
   case 2: JOptionPane.showMessageDialog( null,
                       "Advertencia",
                       "Mensaje de advertencia",
                       JOptionPane.WARNING_MESSAGE);
       break;
   case 3: JOptionPane.showMessageDialog( null,
                       "Pregunta",
                       "Mensaje de interrogación",
                       JOptionPane.QUESTION_MESSAGE);
       break;
   case 4: JOptionPane.showMessageDialog( null,
                       "Le comunicamos que...",
                       "Mensaje normal",
                       JOptionPane.PLAIN_MESSAGE);
       break;
  }
 }
}

AccionOpciones.java
//
//  AccionOpciones.java
//  DemoDialogos
//

import java.awt.event.*;
import javax.swing.*;

public class AccionOpciones implements ActionListener {
 JLabel jl;
 String[] respuestas = {"YES_OPTION", "NO_OPTION",
 "CANCEL_OPTION", "OK_OPTION", "CLOSED_OPTION"};
 AccionOpciones(JLabel jl) {
  this.jl = jl;
 }
 public void actionPerformed(ActionEvent e) {
  int caso = Integer.parseInt(e.getActionCommand());
  Object[] opciones = {"Soltero", "Casado", 
  "No sabe/No contesta"};
  int resultado = 0;
  switch(caso) {
   case 0:
      Object[] op0 = {"Aceptado"};
      resultado = JOptionPane.showOptionDialog( null,
             "La bolsa ha subido",
             "Indicación informativa",
             JOptionPane.DEFAULT_OPTION,
             JOptionPane.INFORMATION_MESSAGE,
             null,
             op0,
             op0[0]);
      break;
   case 1:
      Object[] op1 = {"Aceptar", "Rechazar"};
      resultado = JOptionPane.showOptionDialog( null,
             "Por favor, indique si es aplicable:",
             "Exención de IVA",
             JOptionPane.YES_NO_OPTION,
             JOptionPane.INFORMATION_MESSAGE,
             null,
             op1,
             op1[0]);
      break;
   case 2:
      Object[] op2 = {"Abrir cuenta", "Cerrar cuenta",
       "Cancelar"};
      resultado = JOptionPane.showOptionDialog( null,
             "Indique lo que desea hacer con esta cuenta:",
             "Estado de cuenta",
             JOptionPane.YES_NO_CANCEL_OPTION,
             JOptionPane.INFORMATION_MESSAGE,
             null,
             op2,
             op2[0]);
      break;
   case 3:
      Object[] op3 = {"Imprimir", "Cancelar"};
      resultado = JOptionPane.showOptionDialog( null,
             "¿Desea imprimir este documento?",
             "Impresión",
             JOptionPane.OK_CANCEL_OPTION,
             JOptionPane.INFORMATION_MESSAGE,
             null,
             op3,
             op3[0]);
      break;
  }// switch
  jl.setText("Se ha pulsado la opción "
   + respuestas[resultado]);
 }
}

DemoDialogos.java
//
//  DemoDialogos.java
//

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class DemoDialogos extends JFrame5{
  JLabel jl;
    public DemoDialogos() {
   super("DEMOSTRACIîN DE DIÁLOGOS ESTÁNDAR");
   ActionListener aMensajes, aConfirmacion, 
    aEntrada, aOpciones,aValor;
   jl = new JLabel("No se ha seleccionado ninguna opción");
   jl.setPreferredSize(new Dimension(300,200));
   jl.setHorizontalAlignment(SwingConstants.CENTER);
   
   jmb = new JMenuBar();
   
   //Preparamos el menú Archivo para salir
   salir = new JMenuItem("Salir");
   salir.addActionListener(new Finis());
   archivo = new JMenu("Archivo");
   archivo.add(salir);
   // Lo aˆadimos a la barra de menús
   jmb.add(archivo);
   // Preparamos el menú Mensajes
   // En este tipo de cuadros de diálogo sólo
   //se puede variar el mensaje mostrado,
   // el t‚tulo y el icono.
   //
   String[] nMensajes = {"Error...", "Información...",
    "Advertencia...", "Pregunta...", "Normal..."};
   aMensajes = new AccionMensajes(jl);
   JMenu mensajes = prepararMenu("Mensajes", nMensajes,
    aMensajes);
   jmb.add(mensajes);
   //
   // Preparamos el menú Confirmación
   // Solo se pueden hacer variar el mensajes, el t‚tulo 
   // y el grupo de opciones.
   // Las opciones son por defecto, si/no,si/no/cancelar 
   // y ok/cancelar
   // Se devuelven constantes que denotan si, no, cancelar,
   // ok o cerrado
   //
   String[] nConfirmacion = {"Opcion POR DEFECTO...",
     "Opcion SI/NO...",
    "Opcion SI/NO/CANCELAR...", "Opción OK/CANCELAR" };
   aConfirmacion = new AccionConfirmacion(jl);
   JMenu confirmacion = prepararMenu("Confirmacion",
    nConfirmacion, 
    aConfirmacion);
   jmb.add(confirmacion);
   //
   // Preparamos el menú Entrada
   //
   String[] nEntrada = {"Pedir valor...",
    "Seleccionar valor..."};
   aEntrada = new AccionEntrada(jl);
   JMenu entrada = prepararMenu("Entrada", nEntrada, 
    aEntrada);
   jmb.add(entrada);
   //
   // Preparamos el menú Opciones
   //
   String nOpciones[] = {"Opcion POR DEFECTO...", 
    "Opcion SI/NO...", "Opcion SI/NO/CANCELAR...",
    "Opción OK/CANCELAR" };
   aOpciones = new AccionOpciones(jl);
   JMenu opciones = prepararMenu("Opciones", nOpciones,
    aOpciones);
   jmb.add(opciones);
   //
   // Añadimos la barra de opciones al marco y
   // realizamos los ajustes finales.
   setJMenuBar(jmb);
   
   getContentPane().add(jl);
   pack();
   // Centramos el marco en pantalla
   setLocationRelativeTo(null);
   setVisible(true);
    }
//
// Este método resulta útil para no repetir una 
// y otra vez los mismos procedimentos cuando
// vamos a construir un menú
//
  JMenu prepararMenu( String nombre_menu,
                      String[] nombre_opcion,
   ActionListener accion) {
   final int num_opciones = nombre_opcion.length;
   JMenuItem temp;
   JMenu menu = new JMenu(nombre_menu);
   for(int i=0;i<num_opciones;i++)
    {
     temp = new JMenuItem(nombre_opcion[i]);
     temp.addActionListener(accion);
     temp.setActionCommand(i+"");
     menu.add(temp);
    }
   return menu;
  }
    public static void main(String args[]) {
   new DemoDialogos();
    }
}

Finis.java
//
//  Finis.java
//  MenusVarios
//
//

import java.awt.event.*;

public class Finis implements ActionListener {
 public void actionPerformed(ActionEvent e){
  String accion = e.getActionCommand();
  System.out.println("Se ha activado la opción de salida - "
   + accion);
  System.exit(0);
 };
}

JFrame5.java
//
//  JFrame5
//
//

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


public class JFrame5 extends JFrame {
 Dimension dimension_pantalla, dimension_cuadro;
 int xpos, ypos;
 Toolkit tk = Toolkit.getDefaultToolkit();
 JMenuBar jmb = null;
 JMenu archivo = null;
 JMenuItem salir = null;
 JFrame5(String t) {
  super(t==null?"Sin t‚tulo":t);
  salir = new JMenuItem("Salir...");
  salir.addActionListener(new Finis());
  if (t==null)
   {
    archivo = new JMenu("Archivo");
    archivo.add(salir);
    jmb = new JMenuBar();
    jmb.add(archivo);
    setJMenuBar(jmb);
   }
  addWindowListener(
// Si el usuario quiere salir, se ejecuta 
//la rutina de salida
// definida en el menú. Esto es correcto si hay una
// sola ventana (JFrame). Si hay más de una, se puede
// crear un ActionEvent con un ActionCommand que indique
// la ventana que se va a cerrar. Este ActionEvent se pasa
// en una llamada directa, accion_salida.actionPerformed(
// el nuevo ActionEvent).
   new WindowAdapter(){
    public void windowClosing(WindowEvent we) {
     salir.doClick();
    }
   });
 }
}



Comentarios.- A estos archivos es preciso añadir, desde luego, el oportuno makefile y el manifest correspondiente. El lector interesado encontrará aquí todo el material.