====== GUIs en Java ====== ===== Pequeña introducción ===== * Podemos añadir controles a un contenedor (applet o frame) mediante el método de este llamado add, al cual se le pasará el control a introducir. ==== AWT ==== Para crear una ventana debemos implementar una clase que herede de java.awt.Frame. Los métodos que pueden sernos útiles en un frame son: * **show** Mostrar la ventana * **setSize** Dar un tamaño a la ventana ==== Applets ==== * Para la creación de un applet en nuestra página web debemos crear una clase que herede de java.applet.Applet. * Para insertar un applet en un .html debemos insertar un derivado del siguiente tag: * Podemos sobreescribir o usar una serie de métodos para controlar nuestro applet: * **destroy** Se lanza al cerrar el applet * **getParameter** Para recoger el valor de un parámetro indicado en el .html. * **init** Llamado al inicializar el applet * **isActive** Indica si el applet está activo * **resize** Cambia el tamaño del applet * **start** Lo llama el browser para indicar al applet que inicie, se ejecuta después del init. * **stop** Se ejecuta al indicar el browser que el applet pare. * **paint** Llamado al repintar el applet. * **setBackground** Usado para indicar un color de fondo * **repaint** Para volver a llamar al dibujado del applet ===== Eventos ===== ==== Cómo funcionan? ==== Hemos de tener en cuenta que todo lo que veremos aquí, aunque sean para un javax.swing.JFrame, son objetos del paquete java.awt.events. \\ Los eventos en Java funcionan con "escuchadores" y "adaptadores", necesitamos añadir un escuchador para poder controlar el evento (un adaptador es un objeto escuchador más sofisticado), es decir, un control tiene métodos para añadir escuchadores: addComponentListener, addKeyListener, addFocusListener... Todos ellos reciben el objeto que implementa la interfaz correspondiente (nosotros podríamos crear objetos que la implementasen, pero recuerda, deberíamos sobreescribir sus métodos, aunque fuesen innecesarios) o pasarle un objeto nativo de java que ya tenga implementada la interfaz (adaptador), la interface corresponde al Listener, y luego sobreescribir el método que nos interese. \\ Tal vez te preguntes si es necesario crear la nueva clase, hacer que herede, pero, y luego? como llamamos a los métodos de nuestra clase? Gracias a una proiedad de java cuyo nombre no quiero acordarme (creo que son **métodos anónimos**, pero no me hagas mucho caso), puedes hacerlo in situ: \\ P.ej. (código en un método de un JFrame): ... this.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { TeclaApretada(e); } }); ... Hemos llamado al método addKeyListener y pasado un KeyAdapter (este hereda de la interface KeyListener) que hemos creado en la llamada y a la vez le hemos dado ahí el cuerpo. su cuerpo ha sido una sobreescritura del método keyPressed (cuando se ha pulsado la tecla) que llama a otro método de JFrame, TeclaApretada: ... private void TeclaApretada (KeyEvent e) { this.setTitle(e.toString()); } No olvides usar la ayuda para ver las clases que heredan de los escuchadores (adaptadores), o también para comprobar qué métodos puedes sobreescribir. * El método removeXXXListener eliminará el escuchador seleccionado. ==== Eventos de teclado ==== Podemos usar el evento 'keyPressed' del Frame para detectar qué tecla ha sido pulsada. El método correspondiente a este evento nos trae un objeto java.awt.event.KeyEvent, ese objeto tiene un método llamado getKeyCode() que devuelve un int, ese int podemos compararlo con constantes existentes dentro de la misma clase KeyEvent. \\ Como bien sabemos, podemos usar estas constantes en un switch: switch(evt.getKeyCode()) { KeyEvent.VK_SPACE: ... Para controlar el KeyDown usaremos el método KeyPressed y el KeyUp con el KeyReleassed. ==== Eventos de Mouse ==== * El evento MouseMoved ocurre cuando el mouse se desplaza por el frame, el objeto que nos trae este objeto es java.awt.event.MouseEvent, y mediante sus métodos getX y getY podemos saber la posición actual del mouse. * El evento MouseClicked ocurre cuando se hace un click con el ratón. ==== Eventos de formulario (resize) ==== Para capturar el evento que indica que una venta cambia de tamaño necesitamos un component listener.... addComponentListener(new java.awt.event.ComponentAdapter() { public void componentResized(java.awt.event.ComponentEvent evt) { ... } }); ==== Crear un evento personalizado ==== Para crear nuestros eventos tendremos que lidiar con la clase **java.util.EventObject** y con la interface **java.util.EventListener**. Cada clase que represente un evento heredará de EventObject, para que podamos capturar concretamente este evento tendremos que programar otra interface listener que herede de EventListener, ésta será implementada por la clase que tenga que capturarlo. Por lo tanto en este juego tenemos unos cuantos jugadores: - Interface que extiende EventListener. - Clase que implementa a la interface anterior (1). - Clase que representa el evento, hereda de EventObject. - Clase que lanza el evento. Veamos una posible codificación para un evento, la clase EventObject obliga a que al constructor se le pase un objeto (este ha de ser el que crea el evento): public class evento extends java.util.EventObject { private String str; public evento (Object obj, String msg) { super(obj); this.str = msg; } public String getStr () { return this.str; } } Un ejemplo de la interface: public interface myIntListener extends EventListener { public void Captura (evento evt); } Y de la clase que implementa la interface, esta cuando se lanza el envento escribirá por pantalla el string que viene dentro: public class myListener implements myIntListener { public void Captura(evento evt) { System.out.println(evt.getStr()); } } Y aquí la clase que lanza el evento, ''list'' es un objeto asignado de la clase ''myListener'' o de la interface ''myIntListener'', esto no importa: this.list.Captura(new evento(this, "afds")); === Ejemplo === Otro ejemplo sería utilizando esta misma interface ''myIntListener'', este mismo EventObject ''evento'' y dos formularios, uno con un botón que al pulsarse lanzará el evento al segundo formulario que cambiará su título con el texto que le venga en el objeto ''evento''. Para que esto pueda salir bien el segundo formulario debe implementar ''myIntListener''. En el primer formulario habría este código: myIntListener esc; public void setListener (myIntListener mil) { this.esc = mil; } Una vez llamado a este método ''setListener'' pasándole por parámetro el segundo formulario se lanzaría con la siguiente línea: this.esc.Captura(new evento(this, "título")); El segundo formulario sería algo parecido a esto: public class NewJFrame1 extends javax.swing.JFrame implements myIntListener { public void Captura(evento evt) { this.setTitle(evt.getStr()); } } Aunque el lanzador del evento perfectamente podría tener un array con más listeners. No? ===== Controles ===== ==== Listas ==== El control Lista en Java es el ''javax.Swing.JList'', este puede ser de tres tipos según su forma de seleccionar los elementos internos: - **SINGLE_SELECTION**, cuando sólo puedes seleccionar un elemento. - **SINGLE_SELECTION_INTERVAL**, cuando puedes seleccionar varios contiguos. - **MULTIPLE_SELECTION_INTERVAL**, cuando puedes seleccionar varios elementos. Estas son constantes estáticas dentro de la clase ''javax.swing.ListSelectionModel'' con valores enteros los cuales has de pasar al método ''setSelectionMode'' de la lista. === Cómo manejar los elementos una lista === Para rellenar una lista se utilizan los ListModel, estos son unos objetos que rellenas de elementos y que luego se pasan a la lista mediante el método de esta ''setListModel''. Estos objetos permiten añadir elementos mediante métodos como ''add'' o ''addElement'', eliminarlos con los ''remove'', etc. \\ Para recoger el ListModel de una lista utilizarás el método ''getListModel'' de esta. ===== Cómo... ===== ==== Mensajes ==== La clase para crear mensajes es la ''javax.swing.JOptionPane'', esta tiene un montón de métodos estáticos que te muestran los famosos cuadros de mensajes: javax.swing.JOptionPane.showMessageDialog(this, e.getMessage(), "Error!", javax.swing.JOptionPane.ERROR_MESSAGE); javax.swing.JOptionPane.showMessageDialog(this, strMsg); ==== Recoger información del mouse ==== Podemos conseguir información sobre la posición actual del mouse mediante el método estático //java.awt.MouseInfo.getPointerInfo().getLocation()//, pero este método no nos dará la posición relativa al Frame, sino la total respecto a la pantalla. ==== Cambiar el tipo de cursor ==== En un control veremos el método "setCursor", a este hay que pasarle un objeto Cursor que debemos crear con un integer. Este integer lo sacaremos de las constantes de la clase Cursor. Mira como se cambia un cursor de flecha a uno de mano: //this.setCursor(new Cursor(Cursor.HAND_CURSOR));// ==== Hacer el cursor invisible ==== Las próximas líneas de código simulan un cursor de mouse invisible, para ello lo que hacen es crear un nuevo cursor mediante una imágen vacía y asignarla al frame. Toolkit tk = Toolkit.getDefaultToolkit(); Cursor invisCursor = tk.createCustomCursor(tk.createImage(""),new Point(),null); setCursor(invisCursor); ==== Utilizar un timer ==== //javax.swing.Timer// es una clase que nos permite implementar un timer, es muy intuitiva, con métodos como start, stop, setInteval... Sólo decir que en el constructor tendrás que pasarle un objeto que implemente la interface ActionListener, en su método ActionPerformed podrás codificar el toque de relog que toque. ==== Crear un formulario modal ==== Existe la clase **javax.swing.JDialog**, si heredas de ella puedes utilizar un constructor suyo al cual le pasas un boolean que indica si es o no modal. public class optionsDialog extends javax.swing.JDialog { public optionsDialog(java.awt.Frame parent) { super(parent, "Opciones", true); initComponents(); } ... Luego manejarás la ventana mediante el método ''setVisible''. ==== Mostrar las ventanas de Abrir\Guardar fichero ==== Para mostrar estas ventanas tenemos que crear un objeto JFileChooser: javax.swing.JFileChooser jfc = new JFileChooser(); Este contiene los métodos ''showOpenDialog'' y ''showOpenDialog'' que son los encargados de mostrar estas ventanas. Una vez son mostradas el programa no continuará hasta que el usuario no seleccione un fichero o aprete el botón //Cancelar//. Si el usuario escoge un fichero este método devuelve un integer con valor 0, el fichero escogido lo devolverá el método ''getSelectedFile'' del JFileChooser. if (jfc.showOpenDialog(this) == 0) { java.io.File f = jfc.getSelectedFile(); ... ==== Añadir scrolls a un control ==== Existe un control especial llamado ''javax.swing.JScrollPane'', este permite añadir barras de scroll a otros controles como son los cuadros de textos o las listas. Se añade al formulario como se añadiría otro control cualquiera, justo en la posición donde se añadirá el control al cual deseas añadir barras de scroll. Luego, le pasas al método ''setView'' de su ViewPort (para acceder a esta llama al ''getViewport'') el control escogido. JList dataList; ... JScrollPane scrollPane = new JScrollPane(); scrollPane.getViewport().setView(dataList); ===== Tips ===== * Para indicar si un frame puede cambiarse de tamaño utilizaremos el método //setResizable//. * Indicar que la aplicación se acabe al cerrarse el formulario, en el frame: //this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// * Saber la localización de la ventana en la pantalla: método// getBounds//. * Para que una label tenga texto subrayado asigna el texto de la siguiente forma: //jLabel4.setText("Nuevo - Desde archivo");//