Carlos Montenegro Programación de Interfaces de Usuario y Applets Java Carlos Montenegro Introducción Las interfaces de usuario gráficas son la evolución de las interfaces de usuario de comandos Para ciertas tareas, las GUI permiten un mayor rendimiento en aquello que se puede realizar con un programa Desde la explosión que supuso Internet en los años 90, HTML ha quedado bastante obsoleto en muchas materias Una de ellas es el desarrollo de aplicaciones completas servidas desde la web Desde 1995 Java ofrece la posibilidad de ejecutar aplicaciones Java dentro del navegador Carlos Montenegro Interfaces Gráficas de Usuario Permiten hacer programas que sean más sencillos de manejar En Java existen 2 tecnologías para desarrollar GUI: AWT (Abstract Window Toolkit) Swing Carlos Montenegro AWT AWT fue la primera tecnología Java para poder desarrollar aplicaciones gráficas (1995) Resultó una de las mayores competencias hacia lo que anteriormente dominaban Visual Basic y Delphi Es una API que permite la creación de elementos gráficos en una aplicación Es una abstracción de los elementos gráficos nativos del sistema operativo que esté ejecutando nuestra aplicación Java Carlos Montenegro Swing (SWING) Es una evolución de AWT El problema que tenía AWT es que las aplicaciones se veían diferentes según el sistema operativo Una de las premisas de Java era: “write once, run everywhere”, pero esto no se cumplía si las aplicaciones debían ser reescritas según para qué SO Sin embargo, al no utilizar los elementos gráficos nativos del SO es más lento que AWT (hoy día eso no es un problema) Carlos Montenegro Hola Mundo Swing import java.awt.*; import javax.swing.*; public class Main { public static void main(String[] args) { JFrame frame = new JFrame("Prueba"); frame.getContentPane().add(new JLabel("Hola Mundo!"), BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } } Carlos Montenegro Carlos Montenegro Layouts Crear una interfaz Swing es básicamente ir añadiendo objetos a contenedores (JFrame, JPanel…) Java trata de crear interfaces independientes del tamaño del contenedor Para saber dónde y cómo se colocarán los elementos gráficos en un contenedor es necesario especificar un Layout BorderLayout FlowLayout GridLayout GridBagLayout GroupLayout Carlos Montenegro BorderLayout Posiciona los elementos en base a una de 5 posiciones posibles Norte Sur Este Oeste Centro Cuando se añade un componente al contenedor se indica la orientación Es el Layout por defecto Carlos Montenegro BorderLayout Carlos Montenegro FlowLayout Los elementos se disponen de tal forma que se colocan unos a continuación de otros Cuando se crea un FlowLayout se puede especificar el alineamiento (izquierda, derecha, centrado) Por ejemplo: frame.getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT)); Es parecido al alineamiento que hace cualquier página web de sus elementos, por lo que si cambia el tamaño del contenedor se ajustará automáticamente Carlos Montenegro GridLayout Es un tipo de disposición de elementos gráficos donde se colocan como si fuera una tabla de unas determinadas filas y columnas new GridLayout(filas, columnas) Los elementos se disponen por defecto así: Carlos Montenegro GridBagLayout Más flexible que GridLayout, pero mucho más complicado de usar Habitualmente era el usado en IDEs, de forma que el desarrollador no necesite saber exactamente cómo funciona Es más o menos equivalente a una tabla en HTML, donde las celdas pueden expandirse hacia otras filas u otras columnas (gridheight, gridwidth) Cada elemento puede situarse en una celda concreta (gridx, gridy) Cada elemento tiene un valor de expansión relativo o “peso” (weightx, weighty) Carlos Montenegro GroupLayout Desde Java SE6 (y en anteriores usando librerías externas) es posible usar un gestor de posicionamiento aún más avanzado que GridBagLayout Al igual que el anterior, se suele utilizar a través de un IDE Permite que los elementos se “peguen” a otros Es el más usado para disposiciones complejas Carlos Montenegro Barras de desplazamiento Cuando un componente no cabe o bien se quiere que tenga barras de desplazamiento es necesario utilizar un contenedor especial llamado JScrollPane Todo lo que en él se introduzca, cuando exceda su tamaño podrá desplazarse mediante barras JScrollPane scroll = new JScrollPane(); JTextArea texto = new JTextArea("Hola Mundo!"); scroll.getViewport().add(texto); frame.getContentPane().add(scroll, BorderLayout.CENTER); Carlos Montenegro Eventos Cuando el usuario pulsa un botón es necesario responder a dicho evento Cada componente en Swing tiene su colección de eventos posibles ya que no todos los elementos gráficos tienen el mismo comportamiento Se usan añadiendo clases que implementen la interfaz correspondiente: ActionListener, MouseListener, KeyListener… Carlos Montenegro Eventos JLabel label = new JLabel("Hola Mundo!"); label.addMouseListener(listenerRaton); JButton boton = new JButton("Botón"); boton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(null, "Pulsado!", "Botón", JOptionPane.WARNING_MESSAGE); } }); frame.getContentPane().add(boton, BorderLayout.EAST); frame.getContentPane().add(label, BorderLayout.WEST); Carlos Montenegro Problemas de concurrencia Cuando accedemos a un componente gráfico dentro del hilo que ha sido lanzado por un evento no hay ningún problema Pero cuando lo hacemos desde otro hilo asíncronamente con el hilo principal que despacha los eventos pueden producirse errores Esto ocurre especialmente en aplicaciones que realizan tareas en segundo plano (permiten actualizar la GUI mientras se espera algo) Para evitarlo se utiliza SwingUtilities.invokeLater SwingUtilities.invokeLater(new Runnable() { public void run() { texto.setText(“un texto"); } }); Carlos Montenegro Applets Son aplicaciones gráficas de usuario que permiten ser ejecutadas dentro de un navegador Son la “competencia” de Adobe Flash y Microsoft Silverlight por parte de Sun Apenas se distinguen de hacer una aplicación con Swing En Java existe la clase Applet que habrá que sobrecargar Carlos Montenegro Ejemplo Applet import javax.swing.*; import java.awt.*; public class Applet1 extends JApplet { public void init() { this.add(new JLabel(“Hola Mundo")); } } Carlos Montenegro Hola Mundo Applet <object classid="clsid:CAFEEFAC-­‐0014-­‐0001-­‐0000-­‐ABCDEFFEDCBA" codebase="http://java.sun.com/products/plugin/autodl/jinstall-­‐1_4_1-­‐windows-­‐i586.cab#Version=1,4,1,0" width="100" height="50" > <param name="code" value="Applet1"> <param name= "type" value="application/x-­‐java-­‐applet;jpi-­‐version=1.4.1"> <param name="scriptable" value="false"> <comment> <embed type="application/x-­‐java-­‐applet;jpi-­‐version=1.4.1" CODE="Applet1" width="100" height="50" scriptable="false" pluginspage="http://java.sun.com/products/plugin/index.html#download"> <noembed> </noembed> </embed> </comment> </object> <!-­‐-­‐ <applet code="Applet1" width="100" height="50"> </applet> Carlos Montenegro Ciclo de vida de un Applet Carlos Montenegro Ciclo de vida de un Applet init(): Llamado para inicializar el applet paint(): Para personalizar la forma en que se redibuja el applet. Llamado automáticamente como una parte del update(). start(): Cuando la página con el applet aparece en la pantalla stop(): Cuando la página con el applet desaparece de la pantalla destroy(): Cuando la página se cierra. Carlos Montenegro ReuNlización de applets Un applet no es más que otro tipo de contenedor, por lo que podemos probarlo añadiéndolo JApplet applet = new MiApplet(); JFrame frame = new JFrame(“Prueba"); frame.getContentPane().add(applet); Carlos Montenegro Limitaciones de los applet Toda la ejecución se lleva a cabo en cliente, por lo que se libera al servidor pero no se sabe cómo es el cliente Las aplicaciones no pueden ser muy grandes ya que se transmiten por red Están muy limitados por defecto (salvo con firmado con certificados y policies) para evitar cualquier problema de seguridad Carlos Montenegro Policy de Applets Cuando un applet se inicia busca un fichero llamado .java.policy en el directorio del usuario Permiten sobreescribir los permisos por defecto para los applets Por defecto un applet no puede leer del sistema de ficheros, no puede comunicarse con ningún servidor salvo el suyo propio… etc grant codeBase "http://donde.se/descargo/el/applet/ *" { permission java.io.FilePermission "C:\\Documents and Settings\\usuario\\directorio\\*", "read, write, delete"; }; Carlos Montenegro Gráficos avanzados en Swing En el método paint de cada componente gráfico, se pasa como argumento un objeto Graphic Ese objeto Graphic es un Graphic2D que tiene una serie de métodos para manipular imágenes frame.getContentPane().add(new Panel() { public void paint(Graphics g) { g.setColor(Color.RED); g.drawOval(0, 0, 200, 100); } }, BorderLayout.CENTER);