miércoles, agosto 29, 2007

Ventanas en Java I: JFrame, propiedades, centrar, confirmar al cerrar, eventos


La primera distinción que debemos hacer entre las ventas que vamos a realizar es si las mismas son modales o no. Las modales son aquellas ventas que si o si deben tener una respuesta del usuario antes de continuar, como por ejemplo aquellas ventanas donde se nos pide que confirmemos si queremos guardar un archivo o no. Todas las demás ventanas son no modales.
En estos pequeños tutóriales, voy a desarrollar JFrames, IInternalFrames y JDialog
En el caso de las JFrame las mismas son no modales.

1. JFrame

Para comenzar a crear un JFrame tenemos que crear una ventana que extienda la clase JFrame e implemente la interfaz ActionListener que nos permitirá captar los eventos de los usuarios sobre los componentes Swing que vamos a utilizar (el botón).

public class FrameInicial extends JFrame implements ActionListener{

//variables globales en este caso Irán todos los componentes swing
//Constructor de la case
//Métodos

}

Debemos recordar que siempre que implementemos la interfaz AL deberemos declarar el método actionPerformed(AcrionEvente evento)
El constructor de la clase tendrá la forma:

public FrameInicial() {
try {
metodoSiguiente();
// aquí vamos a poner las propiedades y componentes
this.centrar();
//método mió para centrar
/*confirmacion de salida*/
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e) {
confirmarSalida();
}
});
this.setVisible(true);
//hacemos visible el frame
}
catch (Exception e) {
e.printStackTrace();
}
}

El metodoSiguiente() es un método que cree para ordenar todas las propiedades y los componentes que contendrá nuestra ventana.
Centrar() es un método que nos permitirá centrar la ventana de acuerdo a la resolución que tenga nuestro monitor. Por defecto en java todas las ventanas aparecen en el extremo superior izquierdo.
En cuanto a solicitar una confirmación a la hora de salir lo primero que tenemos que indicar es que la ventana no va a realiza ninguna acción cuando se da el evento de cierre, si esto no se especifica, la ventana sale directamente sin realizar ninguna acción. Esto es en el caso en que tenemos un frame que es el principal de nuestra aplicación y queremos pedirle al usuario que confirme la salida cuando hizo clic en la crucecita del frame.
Lo hacemos con el metodo:

setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE)

confirmarSalida() será el método que pregunte si deseamos salir o no.
Finalmente debemos hacer visible el frame con el método setVisible(true).

1.1 metodoSiguiente()

En este caso vamos a agregarle al frame una label y un botón para cerrar, a medida que vallamos avanzando en los distintos frames voy a ir agregando distintos componentes.
Es una buena costumbre nombrar a los componentes de forma representativa.
Por ejemplo las etiquetas pueden comenzar con lbl_nombre o los botones con btn_nombre, etc. Ya que cuando nuestra aplicación crezca se puede hacer complicado si no tenemos nombre representativos. Otra aclaración es que los componente ya fueron declarados e inicializados globalmente en la case.

private void metodoSiguiente() throws Exception {
this.getContentPane().setLayout( null );//la forma de organizar los componentes
this.setSize(new Dimension(385, 300));
//el tamaño de la ventana
this.setTitle("Hola Swing");
//el titulo
btn_cerrar.setText("Cerrar");
//el boton cerrar
btn_cerrar.setBounds(new Rectangle(250, 220, 120, 25));//tamaño del botón
lbl_hola.setText("Hola Swing");//lo que la etiqueta dirá
lbl_hola.setBounds(new Rectangle(135, 80, 120, 35));//el tamaño de la etiqueta
lbl_hola.setToolTipText("texto emerguente");
//texto mouse por arriba
lbl_hola.setFont(new Font("Dialog", 1, 20));
//la fuente de la etiqueta
lbl_hola.setForeground(Color.red);
//color de la etiqueta
this.btn_cerrar.addActionListener(this);
//para escuchar los eventos.
this.getContentPane().add(lbl_hola, null);//pegar los components en el frame
this.getContentPane().add(btn_cerrar, null);
}


El setLayout es la forma en la que organizamos los componentes dentro del frame, esto nos servirá para cuando el frame cambie de tamaño o se maximice los componentes mantengan un aspecto armónico. Es todo un tema los distintos tipos de layout que existen en java.
El size o tamaño del componente es importante a la hora de centrar el frame en la pantalla, ya que lo utilizaremos para calcular la ubicación en la que debe estar. Se pasa como parámetro un objeto dimensión con los valores del (ancho, alto).
El titulo (setTitle) es el texto que aparecerá en la parte superior del frame, ademas cuando lo minimicemos aparecerá en la barra de herramientas de Windows (o superior)
En el caso del btn_cerrar le diremos cual será el texto con contendrá con setText, el tamaño y la ubicación con el método setBounds que recibe como parámetro un objeto Rectangle con parámetros que indican las coordenadas y tamaño. Los dos primeros son las coordenadas en x e y desde el margen superior izquierdo del frame, y los dos restantes son el tamaño en ancho y alto.
En cuanto a la etiqueta lbl_hola podemos definir que dirá con setText, la ubicación y tamaño con setBounds, y lo que dira cuando pasemos con el Mouse por arriba con setToolTipText, esta misma propiedad puede ser aplicada a otro componentes swing para ir guiando al usuario. Además de ello podemos indicarle cual sera la fuente que la etiqueta tendrá con setFont que recibe como parámetro un objeto del tipo Font que indica (el nombre de la fuente, normal/negrita/itálica, tamaño). Finalmente podemos indicarle el color que tendrá el texto con setForeground que recibirá como parámetro una constante que indique el color o un objeto Color con parámetros (R,G,B).
componente.addActionListener(this) es el método que permite agregar un oyente de eventos a un componente que tendremos dentro del frame. En este caso se lo agregaremos al botón de cerrar por que nos interesa saber cuando el usuario hace un clic en el. Decimos que el parámetro será el frame que creamos por que ya hemos implementado la interfaz ActionListener en el frame si no tendríamos que crearla como lo hicimos en el caso de la ventana.
Bien… ya hemos creado todos los componentes que el frame tendra, ahora tenemos que pegarlos en frame, si no, no serán visibles, esto los haremos con el método add(componete), que tiene como parámetros ya sea el componente solo, o el componente con su correspondiente layout.

Nota: a estas alturas, los que recién comienzan dirán es un kilombo total crear interfaces graficas en Java, pero no se asusten, los entornos de desarrollo tienen sus propias herramientas para crear esto arrastrando y soltando. ¡Es más! este ejemplo fue creado de esa forma. La finalidad es que sepamos que hace cada cosa.

1.2 El método Centrar()

Al igual que el método anterior, éste es un método creado por mí para centrar las ventanas. Como idea se puede crear una clase con el método implementado y después heredarla en otras clases, en fin… son solo idas.

private void centrar(){
Dimension pantalla = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frame =this.getSize();
setLocation((pantalla.width/2-(frame.width/2)),pantalla.height/2-(frame.height/2));
}

Lo primero que realiza el método es tomar la resolución de la pantalla, primero obtiene el toolkit por defecto y después el resolución de la pantalla.
Después el tamaño que le dimo al frame con getSize()
Y finalmente le indicamos la localización del frame en la pantalla con el método setLocation(int x, int y)

1.3 El método confirmarSalida()

A este método lo podremos llamar tanto desde el botón cerrar de la ventana misma como de un botón creado por nosotros mismos. La llamada al método se realizará en los métodos que las interfaces que escuchan los eventos de usuario, en el caso de la ventana es windowClosing(WindowEvent e), y en el caso del botón es actionPerformed(ActionEvent e).

private void confirmarSalida(){
int i =JOptionPane.showConfirmDialog(this,"¿Realmente Desea Salir de Hola Swing?","Confirmar Salida",JOptionPane.YES_NO_OPTION);
if(i==0){
System.exit(0);
}
}

Bien acá hay algo interesante relacionado a las ventanas. JOptionPane es una clase que nos permite hacer cuadros de diálogos. En el caso del método showConfirmDialog nos devolverá un entero con el valor de la elección del usuario. (En este caso 0 para si, 1 para no). Veremos más opciones cuando trate diálogos en Java.
El método exit(int status) de la clase System nos permitirá cerrar nuestra aplicación.
Debemos distinguirlos del método JFrame.setVisible(boolean visibilidad) del frame que nos permite cerrar la ventana sin salir de la aplicación.

1.1 El método actionPerformed(ActionEvent evento)

Este método nos permitirá captar los eventos realizados por el usuario sobre algún componente swing, en nuestro caso será el botón.

public void actionPerformed(ActionEvent e){
if(e.getSource()==this.btn_cerrar){
confirmarSalida();
}
}

Lo primero que realizamos dentro del método es preguntar cual es la fuente del evento, esto lo hacemos en caso de que tengamos varios botones a los cuales le asignamos el oyente de eventos. Si la fuente del evento es el botón cerrar, llamamos el método confirmar salida.

1.2 La clase Principal

Es una buena costumbre tener una clase que contenga el método main y desde la cual llamar al formulario de entrada a la aplicación.

public class Principal {
public Principal() {
FrameInicial f =new FrameInicial();
}
public static void main(String[] args) {
Principal principal = new Principal();
}
}

8 comentarios:

Antonio de Mora dijo...

Caballero: excelente artículo, y muy atractivo a la vista su blog, necesito tomarme el tiempo para adentrar en el, me ha hechizado de alguna manera, camarada. Estoy batallando para hacer una especie de Jeopardy! en java, y como nunca he programado mas que en C# y C++, si estoy sufriendo en esta incursión a tan genial lenguaje. Espero poder escribir pronto en su blog de nuevo.
Suerte, y siga así.
Besos!
P.D. Por cierto, dese una vuelta x mi blog, le dejo el link http://tu-linux.blogspot.com

aro dijo...

gracias viejo. Un abrazo y me doy una vuelta seguro

Anónimo dijo...

hola, antom, la verdad muy bueno tu programacion, solo te quiero hacer una pregunta , yo eh probado tu programa pero tengo un problema con esta parte
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e) {
confirmarSalida();
}
});
me subraya WindowAdapter()re rojo .
lo que pense es que no habias echo ese metodo por que me sale una ventanita chiquita no mas.

sheba-jose dijo...

oyes como le ago para que me aparesca una ventana que me inhabiliet la otra. Por ejemplo cuando habre una venta de abrir en cualquier programa la que esta atras se inhabilita o sea que no puedes hacer nada ahi hasta que no aceptes o canceles esa ventana. Espero que me entiendas espero tu respuesta. Es sobre java

aro dijo...

lo que mencionas sheba es una ventana modal y esta explicada en alguno de los post.
Saludos.

Anónimo dijo...

camarada con respecto a lo siguiente
no me funciona cuando le da cerrar con la boton cerrar de la ventana, el boton de la propia ventana que se encuentra en la parte superior derecha. xD

addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e) {
confirmarSalida();
}
});

si me muestra el mensaje pero aunque le diga que no se cierre, de todos modos lo hace;
xD

espero tu respuesta si fueras tan amable xD

aro dijo...

Ups! la verdad es que cuando este codigo fue escrito (hace mucho tiempo), se probo y todo, dejame revisar un poco el codigo cuando tenga un tiempito... y si le encuentro al solucion, la posteo! abrazo

manfarre dijo...

marco.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
marco.addWindowListener(new WindowAdapter(){
public void cerrarmarco(WindowEvent e){System.exit(0);}
});
nota marco es mi JFrame saludos ojala les sirva