Interfaces de usuario [Interfaces de usuario con Java] M. en C. Sergio Luis Pérez Pérez UAM C UAJIMALPA , M ÉXICO, D. F. Trimestre 13-O Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 1 / 37 Breve historia a cerca de GUI’s en Java Breve historia a cerca de GUI’s en Java I Java fue inventado en 1995 por James Gosling de Sun Microsystems. La primera biblioteca de Java (1.0) utilizada para este propósito no tuvo éxito. Después, con la herramienta AWT (Abstract Windowing Toolkit) tampoco se tuvo éxito pues era muy pobre. La AWT de Java 1.1 mejoró significativamente, utilizando el concepto de modelo de sucesos, además apareció JavaBeans. Los JavaBeans son un modelo de componentes creado para la construcción de aplicaciones en Java. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 2 / 37 Breve historia a cerca de GUI’s en Java Breve historia a cerca de GUI’s en Java II Después con Java 2 (JDK 1.2) se transformó todo a una moderna biblioteca llamada Swing. Algunas caracterı́sticas de swing son: JavaBeans es el marco de trabajo para Swing. JavaBean y Swing permiten generar aplicaciones rápidamente. Los constructores de interfaces automáticos generan código comprensible. Sin embargo, existen otras alternativas a Swing como SWT patrocinado por IBM y desarrollado por Eclipse. También la herramienta Flex de Macromedia para el desarrollo de interfaces Flash. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 3 / 37 Fundamentos de Swing Fundamentos de Swing I La mayorı́a de aplicaciones Swing se construyen dentro de JFrame, que en sı́ crea la ventana. setDefaultCloseOperation() le dice a JFrame lo que debe hacer cuando el usuario ejecute una operación de cierre. La constante EXIT ON CLOSE le dice que salga del programa. setSize establece el tamaño de la ventana en pı́xeles. Si no se establece setVisible(true) no podrı́amos ver la ventana. Ver ejemplo HelloSwing.java. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 4 / 37 Fundamentos de Swing Fundamentos de Swing II Para crear etiquetas utilizamos JLabel. No es muy recomendable permitir que un sólo hilo (por ejemplo main) escriba directamente en los componentes GUI. Swing dispone de su propio hilo dedicado a recibir sucesos de la interfaz de usuario y a actualizar la pantalla. Ver ejemplo HelloLabel.java. La otra manera de hacer lo mismo es sin manipular directamente la etiqueta JLabel. Para ello existe el concepto de despacho de sucesos de Swing. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 5 / 37 Fundamentos de Swing Fundamentos de Swing III Esto se realiza mediante SwingUtilities.invokeLater() al cual se le entrega una tarea y la coloca en la cola de sucesos para que la ejecute. Se crea un objeto Runnable y el hilo de despacho se encarga de realizar la manipulación real. Si todo el programa emplea esta técnica entonces no habrá colisiones entre hilos. Ver ejemplo SubmitLabelManipulationTask.java. De manera que incluso el arranque del programa debe realizarse utilizando SwingUtilities.invokeLater(). Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 6 / 37 Fundamentos de Swing Fundamentos de Swing IV Ver ejemplo SubmitSwingProgram.java. Cuando introducimos una llamada sleep dentro de un hilo de despacho, éste es suspendido y no se completa hasta que sleep termina su ejecución. Para reducir redundancia de código se sugiere crear entornos de visualización genéricos para no tener que estar reescribiendo código. Ver ejemplo SwingConsole.java. Ejercicios: Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 7 / 37 Fundamentos de Swing Fundamentos de Swing V 1 Realice una modificación a HelloLabel.java para demostrar que la adición de etiquetas es dinámica. El programa debe permitir añadir un número arbitrario de etiquetas. 2 Realice una modificación a SubmitSwingProgram.java para que utilice SwingConsole.java. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 8 / 37 Fundamentos de Swing Definición de botones Definición de botones I Para crear botones se utiliza JButton junto con la etiqueta que se desee incluir en el botón. Lo ideal es crear un objeto JButton que pueda ser referenciado posteriormente. JButton es un componente con su propia ventana de tamaño pequeño. Este se pintará automáticamente como parte de cada actualización. Lo anterior implica que los botones no requieren algún tipo de control y por tanto se repintan solos. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 9 / 37 Fundamentos de Swing Definición de botones Definición de botones II Lo ideal es insertar los botones dentro del constructor de la clase. Para colocar varios botones se debe utilizar lo que se conoce como un gestor de disposición de tipo FlowLayout. El gestor de disposición es la forma en que el panel decide implı́citamente donde colocar los controles. El comportamiento por defecto es utilizar el gestor BorderLayout. Dicho gestor no es adecuado pues sólo consiste en cubrir completamente cada control con los que se vayan agregando. Ver Button1.java. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 10 / 37 Fundamentos de Swing Captura de sucesos Captura de sucesos I La captura de sucesos consiste en conectar los sucesos con el código que debe responder a esos sucesos. Para esto se debe separar la interfaz de la implementación. Para registrar el suceso que deseamos ocurra, por ejemplo al presionar un botón, utilizamos AddActionListener. La interfaz ActionListener contiene un único método denominado actionPerformed. Dicho método será invocado cada vez que se presione el botón. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 11 / 37 Fundamentos de Swing Captura de sucesos Captura de sucesos II actionPerformed recibe un argumento de tipo ActionEvent que contiene toda la información acerca del suceso y de dónde se ha producido. Ver Button2.java. El método getSource() de un ActionEvent devuelve el objeto en que se ha originado el suceso. Otra manera de codificar la clase ActionListener es mediante una clase interna anónima. Las clases internas anónimas son muy similares a las clases locales, pero sin nombre. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 12 / 37 Fundamentos de Swing Captura de sucesos Captura de sucesos III Como la clase anónima no tiene nombre sólo se puede crear un único objeto y no se pueden definir constructores. Cabe destacar que no existen interfaces anónimas. Ver Button2b.java. Ejercicio: 1 Realice una aplicación utilizando la clase SwingConsole que contenga tres botones y un campo de texto. Si presiona los presiona los primeros dos escriba en el área de texto los nombres de los botones, si presiona el tercero escriba la concatenación del texto actual en el área de texto más el nombre del tercer botón. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 13 / 37 Fundamentos de Swing Áreas de texto Áreas de texto I Un área de texto JTextArea se parece a un campo JTextField con la diferencia que el primero puede tener múltiples lı́neas de texto y mayor funcionalidad. Con el método append() podemos agregar datos en el componente JTextArea. Cuando se añade el control JTextArea a la ventana JFrame, se suele introducir dentro de un JScrollPane con la finalidad de controlar el desplazamiento de pantalla. Ver TextArea. Ejercicio: Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 14 / 37 Fundamentos de Swing Áreas de texto Áreas de texto II 1 Realice una aplicación utilizando la clase SwingConsole. 2 Con base en el ejemplo TextArea, su nueva aplicación debe permitir agregar estados en la estructura Map definida en la clase Estados mediante un botón “Agregar estados” con sus respectivas capitales. 3 Para lo anterior utilice dos campos adicionales JTextField, uno para el Estado y otro para la Capital. 4 Cuando presione el botón “Agregar” de la aplicación original TextArea, debe desplegar los estados que ya estaban más lo que haya agregado durante la vida de su aplicación. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 15 / 37 Fundamentos de Swing Control de la disposición Control de la disposición I El control de la disposición es la forma en como se colocan los componentes en una ventana. El gestor de diseño (layout manager) decide cómo se colocan los componentes basándose en el orden de cómo se agregan a la pantalla con add(). Los gestores de diseño se adaptan a las dimensiones de la ventana utilizada. JApplet, JFrame, JWindow, JPanel, entre otros, pueden visualizar objetos Component. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 16 / 37 Fundamentos de Swing Control de la disposición Control de la disposición II En Container el método setLayout() permite elegir un gestor de diseño diferente. Algunos gestores de diseño son: BorderLayout. FlowLayout. GridLayout. GridBagLayout. BoxLayout. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 17 / 37 Fundamentos de Swing Control de la disposición Control de la disposición III BorderLayout Es el gestor de diseño por defecto. Este gestor toma lo agregado con add y lo coloca en el centro, estirando todo hasta alcanzar los bordes. Este gestor de diseño considera que existen cinco regiones principales en la ventana: Norte, Sur, Este, Oeste y Centro. Para especificar una región se utiliza el método sobrecargado add y las constantes BorderLayout.NORTH, . . . . Ej.: add(BorderLayout.NORTH, componente). Ver BorderLayout1. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 18 / 37 Fundamentos de Swing Control de la disposición Control de la disposición IV FlowLayout Este gestor coloca los elementos en la ventana de izquierda a derecha y luego de arriba hacia abajo. Los componentes son mostrados en su tamaño original. Se especifica utilizando el método setLayout(new FlowLayout()). Ver FlowLayout1. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 19 / 37 Fundamentos de Swing Control de la disposición Control de la disposición V GridLayout Este gestor permite construir una tabla de componentes. Los componentes son colocados de izquierda a derecha y luego de arriba hacia abajo dentro de la tabla. Se debe especificar el número de filas y columnas mediante el constructor. Se especifica utilizando el método setLayout(new GridLayout()). Ver GridLayout1. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 20 / 37 Fundamentos de Swing Control de la disposición Control de la disposición VI GridBagLayout Permite decidir cómo disponer exactamente de las regiones en la ventana. Está pensado para la generación automática de código dentro del diseño de GUI’s. Es complejo de utilizar, pues requiere especificar las restricciones (posición, altura, ancho) para cada elemento a colocar. Las restricciones son especificadas mediante las clase GridBagConstraints. Se especifica utilizando el método setLayout(new GridBagLayout()). Ver GridBagLayout1. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 21 / 37 Fundamentos de Swing Control de la disposición Control de la disposición VII BoxLayout Es más simple de utilizar que GridBagLayout y proporciona un comportamiento similar. Permite controlar la ubicación de los componentes ya sea de manera horizontal o vertical. También permite proporcionar un espaciado entre componentes. Se especifica utilizando el método setLayout(new BoxLayout()). Ver BoxLayout1. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 22 / 37 Fundamentos de Swing Control de la disposición Control de la disposición VIII Práctica 2 Con lo visto en clase el dı́a de hoy realice una aplicación que permita jugar el juego de gato. Cree una matriz de 3x3 botones. Al inicio los 9 botones están vacı́os. Los jugadores serán X y O y siempre comienza X. Cuando el usuario presione un botón, si este estaba en blanco entonces colocará el caracter correspondiente al turno actual. Cuando el juego termine, muestre en un JTextField el nombre del jugador ganador o bien la palabra “Empate” en caso de haberlo. Agregue un botón que permita reiniciar el juego. 3 Puntos extra: Agregue un botón que dada la configuración actual indique quién serı́a el ganador si ambos jugasen perfectamente. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 23 / 37 Fundamentos de Swing El modelo de sucesos Swing El modelo de sucesos Swing I El modelo de sucesos Swing permite que un componente dispare sucesos. Cada tipo de sucesos se representa por una clase diferente. Cuando un suceso es disparado, éste es recibido por uno o mas escuchadores. El origen de un suceso y el lugar donde el suceso es tratado pueden estar separados. Cada escuchador de sucesos pertenece a una clase que implementa un tipo de interfaz especı́fica. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 24 / 37 Fundamentos de Swing El modelo de sucesos Swing El modelo de sucesos Swing II La estructura general para implementar suceso es mediante los métodos addTipoSucesoListener en el componente encargado de disparar el suceso. Cuando se crea una clase escuchadora se debe implementar la interfaz adecuada. Todos los componentes Swing incluyen métodos addTipoSucesoListener y removeTipoSucesoListener. A continuación se presenta una tabla con los sucesos más comunes. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 25 / 37 Fundamentos de Swing El modelo de sucesos Swing El modelo de sucesos Swing III Suceso, interfaz escuchadora y métodos de adición y de eliminación ActionEvent, ActionListener (add-remove)ActionListener Adjustment(Event-Listener), (add-remove)AdjustmentListener Component(Event-Listener) addComponentListener() removeComponentListener() Container(Event-Listener) addContainerListener() removeContainerListener() Sergio Luis Pérez (UAM C UAJIMALPA) Componentes que soportan este suceso JButton, JList, JTextField, JMenuItem, JPopupMenu Jscrollbar, Adjustable Component→JButton,JPanel JLabel, JList, JScrollBar JTextArea, JTextField, JApplet Container→JApplet,JPanel JFrame, JDialog, JScrollPane JFileDialog, Window Curso de Interfaces de Usuario 26 / 37 Fundamentos de Swing El modelo de sucesos Swing El modelo de sucesos Swing IV Suceso, interfaz escuchadora y métodos de adición y de eliminación FocusEvent, FocusListener (add-remove)FocusListener Key(Event-Listener), (add-remove)KeyListener Mouse(Event-Listener) (add-remove)MouseListener() MouseMotion(Event-Listener) addMouseMotionListener() removeMouseMotionListener() Item(Event-Listener) (add-remove)ItemListener() Sergio Luis Pérez (UAM C UAJIMALPA) Componentes que soportan este suceso Component y sus derivados Component y sus derivados Component y sus derivados Component y sus derivados JCheckBox, JComboBox JList, JCheckBoxMenuItem Curso de Interfaces de Usuario 27 / 37 Fundamentos de Swing El modelo de sucesos Swing El modelo de sucesos Swing V Ver ShowAddListeners. La forma de agregar sucesos es como sigue: 1 Se elije un componente Swing. 2 Con la interfaz anterior podemos verificar el tipo de sucesos asociados al componente (por ejemplo JButton), por ejemplo addMouseListener, addKeyListener. 3 Elegimos los métodos a implementar de la interfaz deseada (por ejemplo MouseListener, KeyListener). 4 Finalmente registramos el método deseado ante el componente para el que deseamos ocurra el suceso. Las interfaces escuchadoras más comunes son: Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 28 / 37 Fundamentos de Swing El modelo de sucesos Swing El modelo de sucesos Swing VI Interfaz escucha/adaptador ActionListener AdjustmentListener ComponentListener ComponentAdapter ContainerListener ContainerAdapter FocusListener FocusAdapter FocusListener FocusAdapter MouseListener MouseAdapter Sergio Luis Pérez (UAM C UAJIMALPA) Métodos de la interfaz actionPerformed(ActionEvent) adjustmentValueChanged (AdjustmentEvent) Component(Hidden-ShownMoved-Resized)(Comp.Event) Component(Added-Removed) (ContainerEvent) focusGained(FocusEvent) focusLost(FocusEvent) key(Pressed-ReleasedTyped)(KeyEvent) mouse(Clicked-EnteredExited-Pressed)(MouseEvent) Curso de Interfaces de Usuario 29 / 37 Fundamentos de Swing Componentes Swing Componentes Swing I Algunos componentes Swing. Botones. Iconos. Sugerencias. Campos de texto. Bordes. Edición de texto. Casillas de verificación. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 30 / 37 Fundamentos de Swing Componentes Swing Componentes Swing II Botones de opción. Cuadros combinados. Cuadros de lista. Tableros con ficha. Recuadros de Mensaje. Menús. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 31 / 37 Fundamentos de Swing Componentes Swing Componentes Swing III Botones Todos los botones, casillas de opción, botones de opción y menús heredan de AbstractButton. Algunos tipos de botones son: JButton. JToggleButton. JCheckBox. JRadioButton. Ver Buttons.java Ver ButtonGroups.java Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 32 / 37 Fundamentos de Swing Componentes Swing Componentes Swing IV Iconos Los iconos pueden ser utilizados dentro de un controlJLabel o de cualquier control que herede de AbstractButton. Se pueden utilizar archivos GIF. Para abrir archivos y tomar la imagen se utiliza la clase ImageIcon. Ver Faces.java. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 33 / 37 Fundamentos de Swing Componentes Swing Componentes Swing V Sugerencias Permiten visualizar sobre los objetos de JComponent pequeños recuadros a un lado del puntero del ratón. Las sugerencias se derivan de JComponent utilizando el método setToolTipText(String). Campos de texto Permiten crear campos de texto utilizando la clase JTextField. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 34 / 37 Fundamentos de Swing Componentes Swing Componentes Swing VI Bordes Pueden ser agregados a cualquier objeto de JComponent mediante el método llamado setBorder(). Además de los bordes predefinidos (TitledBorder, EtchedBorder, LineBorder, MatteBorder, BevelBorder, SoftBevelBorder) se pueden crear nuevos bordes mediante la clase CompoundBorder. Edición de texto El control JTextPane permite crear un potente editor de texto. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 35 / 37 Fundamentos de Swing Componentes Swing Componentes Swing VII Casillas de verificación Estas permiten efectuar elecciones binarias. Se forma por un pequeño recuadro y una etiqueta. El recuadro contiene una ‘x ’ minúscula dependiendo del estado de la selección. Se utiliza un control JCheckBox. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 36 / 37 Fundamentos de Swing Componentes Swing Componentes Swing VIII Botones de opción Son controles que permiten realizar una única selección de entre varias disponibles. Para definir un grupo asociado de botones se utiliza JRadioButton. Dicho control debe ser agregado a un control llamado ButtonGroup. Se puede configurar uno de los botones como encendido por defecto. Sergio Luis Pérez (UAM C UAJIMALPA) Curso de Interfaces de Usuario 37 / 37