sábado, 31 de julio de 2010

La nueva clase SystemTray de Java SE 6

La nueva clase SystemTray permite (si es soportado por el sistema operativo) crear un pequeño ícono en la bandeja de escritorio, de tal manera que pueda accederse a ella sin necesidad de crear una ventana común. Sólo un pequeño ícono que para windows por ejemplo se encuentra cerca del reloj, donde generalmente corren las aplicaciones como Antivirus, reloj, etc...

De hecho creo que este es el artículo mas corto que escrito, debido a lo fácil que se me hizo realizarlo veamos el ejemplo:



package traydemo;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DemoTray {
public static void main(String[] args) {
final TrayIcon icono;
Image imagen = null;
final JFrame ventana = new JFrame("Principal");
if(SystemTray.isSupported()){
SystemTray tray = SystemTray.getSystemTray();
imagen = Toolkit.getDefaultToolkit().
getImage("Tray.jpg");
PopupMenu popup = new PopupMenu();
MenuItem optComenzar = new MenuItem("Comenzar...");
MenuItem optSalir = new MenuItem("Salir");
optSalir.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
optComenzar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ventana.setSize(300,300);
ventana.setVisible(true);
}
});
popup.add(optComenzar);
popup.add(optSalir);
icono = new TrayIcon(imagen, "Tray", popup);
icono.setImageAutoSize(true);
icono.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e){
if(e.getButton() == 1){
ventana.setSize(300,300);
ventana.setVisible(true);
}
}
});
try {
tray.add(icono);
} catch (AWTException e1) {
System.out.println(e1.getStackTrace());
}
}
}
}


Creo que es fácil entender y usar.

Primero que todo hay que preguntar si nuestro sistema operativo soporta SystemTray (es decir, SystemTray.isSupported()) de ser así creo la instancia de SystemTray, elijo la imagen que va a ser colocada en la bandeja de escritorio a través de la clase Image, recuerde que esta imagen debe estar en la misma ruta del proyecto Java.

Creo un menú auxiliar (PopupMenu) que se desplegará si el usuario hace clic secundario en este ícono, tendrá dos opciones comenzar la aplicación (llama a ventana Swing.JFrame principal de la aplicación por supuesto) o salir (System.exit(0)), creo un TrayIcon llamado icono que que será el ícono de la aplicación pasándole la imagen seleccionada, ajusto con setImageAutoSize(true) para que la imagen se ajuste al tamaño del ícono de la bandeja de Escritorio, si el usuario hace clic en el ícono con el botón principal también se desplega la ventana principal. Por último y muy importante es agregar el icono (TrayIcon) al tray, una vez hecho esto, el ícono queda visible en el system tray, es decir, la bandeja de escritorio, cerca del reloj, antivirus, etc...

Bueno esto es todo por ahora, espero haberme explicado y les sea de utilidad este post. Nos vemos en una próxima edición.

sábado, 24 de julio de 2010

Dialogos Modales y No Modales en Java SE 6. Novedades Swing.

Saludos compañeros nos vemos otra vez aquí, para compartir ideas y experiencias de Java. Esta vez le toca el turno a los diálogos modales, mostraremos que conforma el nuevo API de Java SE 6 para crear diálogos modales y evitar diálogos modales, empecemos:

En versiones anteriores de Java ya existía una forma de crear diálogos modales a través del parámetro boolean (modal o no) del constructor de la clase java.awt.Dialog, este parámetro al ser verdadero (true) bloqueaba toda la aplicación y hasta que ella se cerrara no se podía seguir con la aplicación. Veamos un pequeño en ejemplo con este constructor:



package mipaquete;
import javax.swing.*;

public class Marco {
   public static void main(String[] args) {
      JFrame f = new JFrame("");
      f.setAlwaysOnTop(true);
      f.setSize(300,300);
      f.setVisible(true);
      JDialog d = new JDialog(f, "Dialog", true);
      d.setSize(300,300);
      d.setLocationRelativeTo(null);
      d.setVisible(true);
   }
}


Si se ejecuta este párrafo anterior se muestra un Frame y un Diálogo, hasta que no sea cerrado el diálogo no puede tomar el foco el Frame, es decir no tengo acceso a él.

Si tengo una aplicación en la cual deseo que no toda la aplicación sea bloqueada sino sólo parte de ella, puedo hacer uso del nuevo API de Java 6 donde se incluyen dos clases estáticas dentro de la clase Dialog, estas son:


static class ModalityType y static class ModalExclusionType, ambas tienen dentro de sí una enumeracion que indican el nivel de bloqueo que pueden generar.

static class ModalityType, esta clase sirve para definir el tipo de bloqueo, o también llamado alcance del bloqueo en una aplicación, su enumeración contiene:

APPLICATION_MODAL: Bloquea todas las ventanas de la aplicación, excepto las ventanas que se deriven de ella, es decir, las ventanas que estén abiertas para el momento en que se muestra este diálogo quedan bloqueadas, pero si a partir de ese momento se crean nuevas ventanas (ventanas hijas) estas no serán bloqueadas.

DOCUMENT_MODAL: Bloquea la ventana padre de la ventana y su jerarquía superior, es decir bloque las ventanas de donde fue derivada, pero esto no incluyen las ventanas que no pertenecen a esta jerarquía por lo tanto algunas ventanas quedarán sin bloquear.

MODELESS: no bloquea ninguna ventana.

TOOLKIT_MODAL: Bloquea las ventanas de nivel superior que corren en el mismo TOOLKIT.

Podemos excluir del bloqueo a una ventana o diálogo utilizando la clase ModalExclusionType, esta puede excluir del bloqueo según alguna de estas opciones de su enumeración:

APPLICATION_EXCLUDE: La ventana que utiliza este valor de enumeracion no será bloqueada por ningún diálogo de la aplicación.

NO_EXCLUDE: Indica que la ventana no estará excluida del bloqueo si este ocurriera.

TOOLKIT_EXCLUDE: Indica que no se bloqueará esta ventana si se llamase a APPLICATION_MODAL o TOOLKIT_MODAL.

Lo que nos faltaría por ver son los métodos agregados en Java SE 6.0 que nos permiten utilizar estas enumeraciones:

En la clase java.awt.Dialog se incluyeron los métodos setModalityType() que recibe un Dialog.ModalityType para definir el alcance del bloqueo, también se agregó el método getModalityType(), entre otros.

En la clase Windows se incluyó el método setModalExclusionType() que recibe un elemento de la enumeracion ModalExclusionType para definir que tipo de exclusión será aplicada, también se cuenta con el método getModalExclusionType(), el uso es obvio.

También se agregaron los constructores public Dialog(Window owner, String title,Dialog.ModalityType modalityType) y public Dialog(Window owner, String title, Dialog.ModalityType modalityType, GraphicsConfiguration gc), GraphicsConfiguration queda fuera del alcance de este artículo.

Ahora si estamos listos para crear nuestra aplicación con Ventanas y Diálogos modales con las nuevas modalidades Java SE 6.0. Veamos:


package modality;
import java.awt.*;
import java.awt.Dialog.*;
import java.awt.event.*;
import javax.swing.*;

public class ClaseModal {

static JFrame padre;

public static void main(String[] args) {
      padre = new JFrame("Marco1");
      padre.setLayout(new BorderLayout());
      JButton btnNuevaVentana =
        new JButton("Boton Mostrar Hija");
      JLabel etiqueta = new JLabel("Etiqueta");
      etiqueta.setBackground(Color.BLUE);
      padre.add(etiqueta, BorderLayout.CENTER);
      padre.add(btnNuevaVentana, BorderLayout.SOUTH);
      btnNuevaVentana.addActionListener(
        new ActionListener(){
         @Override
         public void actionPerformed(ActionEvent e) {
              JDialog dialogoAuxiliar =
                  new JDialog(padre, "hija",
                    Dialog.ModalityType.DOCUMENT_MODAL);
                  JButton btnSaveAs =
                    new JButton("Save as...");
                  btnSaveAs.addActionListener(
                    new ActionListener(){
                  @Override
             public void actionPerformed(ActionEvent e) {
//Disminucion de sanguia por cuestiones de espacio
               FileDialog fileDialog =
                 new FileDialog(padre,
               "Guardar", FileDialog.SAVE);
               fileDialog.setSize(400,400);
               fileDialog.setVisible(true);
                  }
                  });
                  dialogoAuxiliar.add(btnSaveAs);
                  dialogoAuxiliar.setSize(300,300);
                  dialogoAuxiliar.setLocation(150,150);
                  dialogoAuxiliar.setVisible(true);
   }
});
padre.setSize(300,300);
padre.setVisible(true);
JFrame ventanaIndependiente =
new JFrame("Ventana Independiente");
ventanaIndependiente.setModalExclusionType(
Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
ventanaIndependiente.setSize(500,500);
ventanaIndependiente.setLocation(75, 75);
ventanaIndependiente.setVisible(true);
}
}


Al ejecutar esta aplicación se obtienen 2 ventanas, una ventana Padre y una Independiente. Al hacer click en el botón Mostrar Hija, se desplega una ventana hija que bloquea la padre (DOCUMENT_MODAL), la ventana hija tiene un único botón que llama un FileDialog (Cuadro de dialogo Guardar), este Cuadro de diálogo tampoco bloquea la ventana independiente ya que utiliza a Dialog.ModalExclusionType.APPLICATION_EXCLUDE, si se utilizara Dialog.ModalExclusionType.NO_EXCLUDE o simplemente no se asigna ningún ModalExclusionType, entonces la ventana independiente se bloquearía con el cuadro de diálogo SAVE.

Bueno, espero haberme explicado y este código les ayude a resolver dudas o inquietudes que se les hayan podido encontrar, cualquier pregunta tenemos los comentarios abiertos, para ampliar el tema, o resolver dudas, por mi parte me despido hasta una próxima edición.