Interfaces de Usuario Con Java (2)

64
INTERFACES DE USUARIO CON JAVA Contenido Notas del Documento....................................................................................................... 3 Introducción ..................................................................................................................... 3 Conjunto de Clases ........................................................................................................... 4 Modelo de Programación ............................................................................................. 5 JComponent ..................................................................................................................... 5 Pintado de Componente .............................................................................................. 5 Activar/desactivar componentes ................................................................................. 5 Cuadros y Ventanas .......................................................................................................... 5 Eventos ............................................................................................................................. 8 Receptores y gestores de Eventos................................................................................ 8 Look And Feel ................................................................................................................. 11 Propiedades de Look and feel .................................................................................... 13 Establecer la configuración Look and feel .................................................................. 14 Look and Feels disponibles en el sistema................................................................... 14 Establecer la apariencia.............................................................................................. 14 Redimensionar Componentes. ................................................................................... 15 Cambiar los colores de la apariencia Nimbus ........................................................ 16 Contenedores de alto nivel ............................................................................................ 18 Añadir componentes al Panel Contenedor ................................................................ 19 Añadir una barra de Menú ......................................................................................... 19 Layouts. Posicionar Componentes. ................................................................................ 19 Establecer el Layout ................................................................................................... 19 BorderLayout .............................................................................................................. 19 BoxLayout ................................................................................................................... 21 FlowLayout ................................................................................................................. 22 CardLayout ................................................................................................................. 23 GridBagLayout ............................................................................................................ 23 GridLayout .................................................................................................................. 26 Posicionamiento Absoluto.......................................................................................... 26 Componentes Textuales ................................................................................................. 27 JTextComponent ........................................................................................................ 27 JTextField .................................................................................................................... 27 JPasswordField ........................................................................................................... 28 JFormattedTextField ................................................................................................... 29

Transcript of Interfaces de Usuario Con Java (2)

Page 1: Interfaces de Usuario Con Java (2)

INTERFACES DE USUARIO CON JAVA

Contenido Notas del Documento. ...................................................................................................... 3

Introducción ..................................................................................................................... 3

Conjunto de Clases ........................................................................................................... 4

Modelo de Programación ............................................................................................. 5

JComponent ..................................................................................................................... 5

Pintado de Componente .............................................................................................. 5

Activar/desactivar componentes ................................................................................. 5

Cuadros y Ventanas .......................................................................................................... 5

Eventos ............................................................................................................................. 8

Receptores y gestores de Eventos ................................................................................ 8

Look And Feel ................................................................................................................. 11

Propiedades de Look and feel .................................................................................... 13

Establecer la configuración Look and feel .................................................................. 14

Look and Feels disponibles en el sistema ................................................................... 14

Establecer la apariencia .............................................................................................. 14

Redimensionar Componentes. ................................................................................... 15

Cambiar los colores de la apariencia Nimbus ........................................................ 16

Contenedores de alto nivel ............................................................................................ 18

Añadir componentes al Panel Contenedor ................................................................ 19

Añadir una barra de Menú ......................................................................................... 19

Layouts. Posicionar Componentes. ................................................................................ 19

Establecer el Layout ................................................................................................... 19

BorderLayout .............................................................................................................. 19

BoxLayout ................................................................................................................... 21

FlowLayout ................................................................................................................. 22

CardLayout ................................................................................................................. 23

GridBagLayout ............................................................................................................ 23

GridLayout .................................................................................................................. 26

Posicionamiento Absoluto .......................................................................................... 26

Componentes Textuales ................................................................................................. 27

JTextComponent ........................................................................................................ 27

JTextField .................................................................................................................... 27

JPasswordField ........................................................................................................... 28

JFormattedTextField ................................................................................................... 29

Page 2: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

2 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JEditorPane y JTextPane ............................................................................................. 31

AbstractButton ............................................................................................................... 31

JButton ....................................................................................................................... 32

JToggleButton ............................................................................................................. 33

JCheckBox ................................................................................................................... 33

JRadioButton .............................................................................................................. 34

JCheckBoxMenuItem y JRadioButtonMenuItem ........................................................ 35

Listas ............................................................................................................................... 35

JComboBox ................................................................................................................. 35

JList ............................................................................................................................. 37

Etiquetas. JLabel ............................................................................................................. 38

Spinners. ......................................................................................................................... 39

Uso de Menús ................................................................................................................. 40

Creación de Menús Habituales ................................................................................... 41

Creación de Menús Contextuales ............................................................................... 43

Barras de Botones. JToolBar ........................................................................................... 44

JPanel. GroupBox ............................................................................................................ 45

Cuadros de Diálogo ........................................................................................................ 46

Diálogos Personalizados ............................................................................................. 49

File Choosers .................................................................................................................. 49

Interfaces MDI. Internal Frames ..................................................................................... 52

JSplitPane ....................................................................................................................... 53

JSlider ............................................................................................................................. 55

JTabbedPane .................................................................................................................. 56

JTree ............................................................................................................................... 58

ScrollPanes ..................................................................................................................... 59

ToolTips .......................................................................................................................... 61

Barras de Progreso ......................................................................................................... 61

JProgressBar ............................................................................................................... 62

Temporizadores. Timer. ................................................................................................. 63

Page 3: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

3 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Notas del Documento. Todos los ejemplos de este documento deben incluirse en una clase que herede de un

objeto JFrame.

Introducción Las primeras interfaces de usuario de Java se inician en AWT. AWT es el acrónimo de

Abstract Window Toolkit.

Posteriormente se implemento SWING, que proporciona clases que representan elementos de IU como ventanas, botones, etc. Todo ello englobado en un paquete denominado javax.swing. Forma parte de las JFC (Java Foundation Clases) que son un superconjunto de clases con cientos de interfaces de programación. En este JFC se incluyen:

- AWT. - SWING - Accesibilidad - Interfaces 2D. - Drag & Drop.

Se enfocará en ese capítulo el modelo de Java Swing y los elementos más importantes que se pueden desarrollar con este conjunto de clases.

Page 4: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

4 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Conjunto de Clases Son muchas las clases que componen el paquete de javax.swing, y muchas las

características y acciones que se pueden realizar.

Se muestran a continuación las clases más relevantes y utilizadas

Como se puede apreciar, tenemos un conjunto de clases superiores que heredan de una implementación de Awt.

Es importante destacar las cuatro clases superiores:

- JApplet. - JDialog. Clase principal para crear ventanas de diálogo. - JFrame: Definida comúnmente como una ventana. - JWindow: Se define como un contenedor que se puede mostrar en cualquier parte

de la ventana del usuario, sin barra de título.

El resto de clases como se puede ver heredan de una clase denominada JComponent. Con estas clases se pueden crear la gran mayoría de las interfaces de usuario.

Page 5: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

5 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Modelo de Programación Java Swing soporta el modelo de programación de Delegación. Es decir utiliza un

patrón Modelo-Vista-Controlador. Este patrón permite reducir el esfuerzo de programación para la implementación de sistemas múltiples y sincronizados.

En esencia este método permite separar la estructura, la presentación y el comportamiento de un componente en diferentes piezas; es decir: separar la el objeto de su presentación.

El modelo MVC en JAVA Swing se realiza a través de eventos. Los gestores de eventos son controladores y las fuentes de eventos son modelos. Cuando un controlador cambia o realizar una función, notifica dicha actividad a todos sus observables. Cada componente se encuentra en realidad formando dos piezas. Una, el delegado UI, responsable de la vista y del controlador que se encarga de responder a los eventos, y otra que constituye el propio modelo de datos.

JComponent Como se puede apreciar en la jerarquía de clases, JComponent es el padre de todos los

elementos visuales de Swing. Se comenta a continuación aquellas propiedades y métodos que se consideran importantes o de interés para trabajar con aquellos componentes hijos:

Pintado de Componente Los componentes de Swing se dibujan automáticamente a través del método paint de

la clase JComponent. Sin embargo, se puede cambiar este comportamiento con sólo sobreescribir el método paint de la clase:

public class miBoton extends JButton { @Override public void paint(Graphics g) { g.setColor(Color.red); //g.fillRect(TOP, TOP, TOP, CENTER) g.fillRect(0, 0, this.getSize().width, this.getSize().height); g.setColor(Color.green); g.drawString(" El Texto ", 10, 10); }

En el código anterior, se está creando un nuevo tipo llamado miBoton que se dibuja automáticamente creando un cuadrado rojo según su tamaño, y un texto en color verde.

Activar/desactivar componentes Los componentes Swing se pueden desactivar de tal forma que el usuario no pueda

interactuar directamente con él, ni tampoco aquellos eventos que tienen que ver con la interacción del usuario. La manera de hacerlo es a través del método setEnabled().

Cuadros y Ventanas Se corresponden con los contenedores de más alto nivel que soportan los

componentes Java.

Page 6: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

6 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JWindow no es más que una pantalla gráfica, sin adornos. Habitualmente para hacer ventanas de bienvenida.

JFrame es una subclase de JWindow con borde y sostiene una barra de menús.

La manera de crearlo es más bien sencilla.

- Creamos una clase main (como siempre) que dentro del método main, cree un objeto de tipo JFrame, y le establecemos sus propiedades. public static void main (String[] args) { JFrame f = new JFrame(); f.setTitle("Mi Primera Ventana"); f.setSize(new Dimension(250, 250)); f.setVisible(true); }

El aspecto que mostraría nuestra ventana en un sistema Windows sería el siguiente:

Sin embargo si lo ejecutamos en un sistema BSD, sería:

Como se puede apreciar, la implementación que tiene cada sistema, es diferente, pero el funcionamiento es el mismo, como se va a ver a continuación.

Notar que cuando el usuario cierra la ventana, no se finaliza el proceso que ha iniciado la maquina virtual. Esto es debido a que no se están controlando los eventos de la ventana, e

Page 7: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

7 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

implementado el método de cierre. En cualquier caso, un JFrame puede reaccionar de manera directa sobre la acción de cierre del Componente. Para ello se puede utilizar el método setDefaultCloseOperation(int). Los posibles valores son (definidos como constantes en la interfaz WindowConstants):

- DO_NOTHING_ON_CLOSE= 0 - HIDE_ON_CLOSE=1 - DISPOSE_ON_CLOSE=2 - EXIT_ON_CLOSE=3

Hagamos ahora lo mismo con un JWindow, para ver la diferencia de aspecto que presentan estas dos interfaces.

Este es el aspecto que mostraría un JWindow vacío.

Otra manera de hacer el cierre de una JFrame o Ventana, es mediante la implementación de la interfaz WindowListener. Esta interfaz la podemos implementar desde una propia clase que herede de JFrame e implemente la interfaz anteriormente dicha, o que se implemente automáticamente desde la definición del método. Se muestra a continuación la manera de hacerlo:

Page 8: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

8 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

public class miFrame extends JFrame implements WindowListener { public void windowOpened(WindowEvent e) { throw new UnsupportedOperationException("Not supported yet."); } public void windowClosing(WindowEvent e) { throw new UnsupportedOperationException("Not supported yet."); } public void windowClosed(WindowEvent e) { throw new UnsupportedOperationException("Not supported yet."); } public void windowIconified(WindowEvent e) { throw new UnsupportedOperationException("Not supported yet."); } public void windowDeiconified(WindowEvent e) { throw new UnsupportedOperationException("Not supported yet."); } public void windowActivated(WindowEvent e) { throw new UnsupportedOperationException("Not supported yet."); } public void windowDeactivated(WindowEvent e) { throw new UnsupportedOperationException("Not supported yet."); } }

El método donde se debe implementar el código es windowClosing. Se puede finalizar la aplicación de la siguiente manera (siempre hay que establecer el listener del evento):

public class miFrame extends JFrame implements WindowListener { public miFrame() { this.addWindowListener(this); } public void windowClosing(WindowEvent e) { //throw new UnsupportedOperationException("Not supported yet."); this.dispose(); }

Eventos Los objetos de Swing se comunican entre sí mediante el envío de mensajes o eventos.

Los objetos de SWING pueden lanzar eventos y capturarlos o manejarlos.

Los eventos se envían desde un objeto a uno o más receptores. Un receptor ejecuta los métodos prescritos para manejar esos eventos.

Un objeto de evento es una instancia de una subclase de java.util.EventObject y contiene información acerca de algo que le ha ocurrido a su fuente.

Receptores y gestores de Eventos Un evento se envía pasándolo como un argumento al método controlador de eventos

del objeto receptor. Por ejemplo, ActionEvent se envía siempre a un método llamando actionPerformed() que se encuentra en el objeto receptor.

Page 9: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

9 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

En esencia, nos estamos refiriendo a lo siguiente:

public class otroFrame implements ActionListener { public void actionPerformed(ActionEvent e) { } }

Cualquier objeto que reciba ActionEvent debe implementar la interfaz ActionEvent. Todas las interfaces de gestión de eventos son subinterfaces de java.util.EventListener, que es una interfaz vacía.

Posteriormente debemos indicar a la fuente de eventos, cual va a ser el receptor de eventos. Para recibir eventos, un gestor de eventos se debe registrar con la fuente de eventos, lo cual permite que se capturen esos eventos. Para ello, se debe usar el método addActionListener para añadirlo, o removeActionListener para quitarlo.

public class otroFrame extends JFrame implements ActionListener { JButton btn = null; public otroFrame() { btn = new JButton(); btn.addActionListener(this); this.add(btn); } public void actionPerformed(ActionEvent e) { //Método que se ejecuta al producirse el evento... System.out.println(e.getSource().toString()); } }

En esencia, Java implementa el envío de eventos mediante interfaces. En realidad todos los objetos de Java envían mensajes (eventos) que otros les pueden capturar. Si desde un código (una clase) queremos capturar un determinado evento, debemos registrar esa clase como capturadora de eventos. Sin embargo, la manera que tiene la máquina virtual de Java de mandarnos ese evento es llamando a un determinado método que conozca su firma (nombre incluyendo los parámetros). Esto es sólo posible mediante la implementación de interfaces.

Page 10: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

10 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Por tanto, no debemos olvidar:

- Si queremos que una clase capture los eventos o mensajes de otra, debemos implementar la interfaz correspondiente.

- Registrar la clase capturadora de eventos.

Normalmente, los dos apartados anteriores, se suele hacer en la misma clase como se muestra a continuación:

public class unFrame extends JFrame implements ActionListener { private JButton btn1 = null; public unFrame() { inicializarComponentes(); } private void inicializarComponentes() { this.setLayout(new FlowLayout(FlowLayout.CENTER)); this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); btn1 = new JButton(); btn1.setText("Botón 1"); btn1.setSize(60, 20); btn1.addActionListener(this); this.add(btn1); }

JVM Clase

Interfaz:

- Método N

Implementa

Botón

El botón lanza un mensaje a la JVM

Almacén de clases que capturan eventos

JVM busca las clases que pueden responder a esos eventos, y mediante Polimorfismo, nos llama al método correspondiente

Page 11: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

11 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

public void actionPerformed(ActionEvent e) { if (e.getSource() == btn1) { } else if (e.getSource() == btn2) { } } }

Destacar del código anterior la implementación de la interfaz ActionListener y la adición de la clase como escuchadora de ese tipo de eventos. Para ser más concretos, esta interfaz recibe eventos de acción. Cuando el evento se produce se llama al método actionPerformed.

Look And Feel A continuación se muestra una imagen de aquellos controles de usuario de Java,

alguno de ellos junto con su apariencia en Windows.

Page 12: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

12 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Page 13: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

13 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Propiedades de Look and feel El toolkit de swing nos permite decidir la configuración de la apariencia de la

aplicación. Si no se especifica (look and feel), el administrador de interfaz de usuario de swing determina cual usar. Las opciones de configuración se reducen a:

- Dejar al administrador de interfaces de Swing determinar la configuración. El administrador de configuración determina la apariencia según las preferencias del usuario (guardadas en el sistema). El Java look and feel que trabaja en todas las plataformas se denomina Metal.

- Usar la apariencia nativa de la plataforma en la que se ejecuta la aplicación. Si nos encontramos con un sistema Microsoft, usará la apariencia de la versión del sistema (XP, Vista…). En Mac OS el look and feel que se utiliza se llama Aqua. En

Page 14: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

14 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

sistema Unix (Solaris o Linux) se usa GTK o CDE/Modif según la configuración del usuario.

- Especificar el look and feel. - Crear un tema especial usando el paquete Synth. - Usar una apariencia externa.

Establecer la configuración Look and feel Normalmente no se necesitará interactuar o cambiar la apariencia de la interfaz. Todos

los componente delegan su interfaz (apariencia) a la clase JComponent. Si algún control o componente quisiera cambiar su interfaz bastaría con sobreescribir aquellos métodos de pintado del componente.

Look and Feels disponibles en el sistema JRE proporciona los siguientes Look and Feels:

- CrossPlatformLokAndFeel: Es el Java look and feel (Metal). Tiene la misma apariencia en todas las plataformas, y la apariencia por defecto si no se establece ninguna.

- SystemLookAndFeel. Apariencia nativa. Se establece en tiempo de ejecución. - Synth: paquete para crear nuestras apariencias mediante ficheros XML.

Se muestra un resumen de las apariencias con las que nos podemos encontrar al usar el SystemLookAndFeel.

Plataforma Look and Feel Solaris, Linux with GTK+ 2.2 or later GTK+

Other Solaris, Linux Motif

IBM UNIX IBM*

HP UX HP*

Classic Windows Windows

Windows XP Windows XP

Windows Vista Windows Vista

Macintosh Macintosh Las apariencias GTK, Motif y Windows se proporcionan con el SDK de Java.

Establecer la apariencia Cuando queramos establecer la apariencia de una aplicación, lo haremos como

primera ejecución de la misma. En caso contrario nos podemos encontrar con que el comportamiento de la misma sea indeseado.

Cuando un componente Java Swing quiere pintarse, pregunta al administrador de interfaces (UIManager) el tipo de apariencia que debe mostrar. La clase UIManager, permite además recuperar las apariencias disponibles a aplicar así como establecer una apariencia concreta. A continuación se muestran unos segmentos de código para trabajar con esta clase.

//Nombre de la clase L&F que implementa el L&F por defecto UIManager.getCrossPlatformLookAndFeelClassName(); //Nombre del L&F del sistema UIManager.getSystemLookAndFeelClassName();

Page 15: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

15 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

//Establecer una apariencia en concreto UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());

Redimensionar Componentes. De manera general se puede establecer el tamaño de cualquier componente a

cualquier tamaño mediante el método setSize de JComponent. Sin embargo, algunas veces necesitamos establecer de manera general el tamaño a todos los componentes en función de una configuración del usuario. Por ejemplo: “Mostrar todos los botones de una barra de botones a un tamaño”. Esto se puede hacer en algunas apariencias de Java (L&F’s) mediante el método putClientProperty. Permite establecer los siguientes tamaños: regular, mini, small y large. A continuación se muestra un ejemplo del resultado final:

Para establecer un tamaño al componente haríamos lo siguiente:

btn1.putClientProperty("JComponent.sizeVariant", "mini");

Una vez que tengamos establecido el tamaño, se deberá actualizar la interfaz:

SwingUtilities.updateComponentTreeUI(this);

Este tipo de funcionalidad sólo está en algunas apariencias, como por ejemplo Nimbus1

. Se muestra a continuación el aspecto que presenta. (btn1, es la instancia a la que hace referencia el botón con el texto Botón 1.

El código de la interfaz anterior sería:

public class unFrame extends JFrame

1 Nimbus es una apariencia introducía en Java 6, actualización 10 que utiliza vectorización Java 2D, que permite configurar la apariencia. En el siguiente enlace http://java.sun.com/docs/books/tutorial/uiswing/lookandfeel/_nimbusDefaults.html#primary se recogen todas las constantes de colores, imágenes, propiedades, etc.

Page 16: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

16 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

implements ActionListener { private JButton btn1 = null; private JButton btn2 = null; public unFrame() { inicializarComponentes(); try { UIManager.setLookAndFeel(new NimbusLookAndFeel()); }catch (Exception ex) {System.out.println(ex.toString());} btn1.putClientProperty("JComponent.sizeVariant", "mini"); SwingUtilities.updateComponentTreeUI(this); this.pack(); } private void inicializarComponentes() { //this.setLayout(new GridLayout(2,1,40,40)); this.setLayout(new FlowLayout(FlowLayout.CENTER)); this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); this.setBackground(Color.red); this.setSize(500, 300); btn1 = new JButton(); btn1.setText("Botón 1"); btn2 = new JButton(); btn2.setText("Botón 2"); btn2.setSize(60, 20); btn2.addActionListener(this); this.add(btn1); this.add(btn2); } }

La siguiente imagen muestra la interfaz con el tamaño large y mini.

Cambiar los colores de la apariencia Nimbus Por defecto, el L&F Nimbus tiene establecidos una serie de colores por defecto, que se

pueden cambiar. Estos parámetros se pueden encontrar en la página principal de Nimbus.

Cuando queramos cambiar estos valores, debemos hacerlo antes de establecer el L&F de la interfaz de usuario. El código para ello es el siguiente:

//Cambiar el color base de los componentes UIManager.put("nimbusBase", Color.red); //Cambiar el color del texto de los controles UIManager.put("textForeground", Color.yellow);

Page 17: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

17 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Page 18: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

18 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

La apariencia de los componentes sería la siguiente:

Contenedores de alto nivel Swing proporciona tres contenedores superiores: JFrame, JDialog y JApplet. Cuando se

utilicen estas tres clases, se deberán tener en cuenta los siguientes puntos:

- Un componente gráfico debe ser parte de una jerarquía de contenedores. Tiene que existir un contenedor raíz de alto nivel siempre.

- Cada componente gráfico sólo puede ser contenido una vez. Si se incluye un componente ya contenido en otro contenedor, este desaparece del primero

- Cada contenedor superior, tiene un panel que es el que contiene los componentes visuales en ese contenedor

- Opcionalmente, se puede añadir una barra de menús a un contenedor de alto nivel. Esta barra, por convención se añade en la parte del contenedor, aunque algunas apariencias (L&Fs) como la de Apple (Aqua) permite posicionarla en la parte superior de la ventana.

A continuación se muestra una imagen en la que se indica el contenedor y el panel.

public class unFrame2 extends JFrame { public unFrame2() { super("Frame Dos"); //También añadimos un menu JMenuBar menu = new JMenuBar(); menu.setPreferredSize(new Dimension(this.getWidth(), 20)); this.getContentPane().setBackground(Color.yellow); this.setSize(240, 240); this.setJMenuBar(menu); } }

Page 19: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

19 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Añadir componentes al Panel Contenedor Para añadir un componente es suficiente tener una referencia al panel principal del

contenedor mediante el método getContentPane()

frame.getContentPane().add(new JButton()); Para incluir componentes en el contenedor también se puede usar el método add,

remove. En este caso, cada componente contenido o hijo se incluiría también al panel del contenedor.

Añadir una barra de Menú Para añadir una barra de menús se utilizará el método setJMenuBar.

JMenuBar menu = new JMenuBar(); menu.setPreferredSize(new Dimension(this.getWidth(), 20)); this.setJMenuBar(menu);

Layouts. Posicionar Componentes. Se denominan Layouts a aquellas clases que administran la colocación de los controles

hijos en los contenedores. Implementan la interfaz LayoutManager y determinan la posición y el tamaño de los componentes. Aunque los componentes tengan explícitamente establecido un tamaño, la última palabra la tiene el Layout.

Establecer el Layout Se establece un determinado Layout al crear el Frame o contenedor con el método

setLayout().

BorderLayout Todo panel contenedor se inicializa para usar un BorderLayout; es decir: no es

necesario especificar el tipo de contenedor al crear el JFrame, automáticamente ya se determina un BorderLayout).

La siguiente imagen muestra el comportamiento de un BorderLayout

Un BorderLayout posee cinco áreas fundamentales, que están especificadas por las siguientes constantes2

2 Estas constantes son diferentes en el JDK 1.3 y anteriores. Las posiciones se establecían según los puntos cardinales

:

Page 20: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

20 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

- PAGE_START - PAGE_END - LINE_START - LINE_END - CENTER

Veamos el ejemplo de posicionamiento de la ventana anterior

public class FrameBorderLayout extends JFrame { public FrameBorderLayout() { super("BorderLayout"); Container pane= getContentPane(); JButton button = new JButton("Button 1 (PAGE_START)"); pane.add(button, BorderLayout.PAGE_START); button = new JButton("Button 2 (CENTER)"); button.setPreferredSize(new Dimension(200, 100)); pane.add(button, BorderLayout.CENTER); button = new JButton("Button 3 (LINE_START)"); pane.add(button, BorderLayout.LINE_START); button = new JButton("Long-Named Button 4 (PAGE_END)"); pane.add(button, BorderLayout.PAGE_END); button = new JButton("5 (LINE_END)"); pane.add(button, BorderLayout.LINE_END); } }

Cuando la ventana anterior se maximiza, esta ocupa la máxima parte central posible. El resto de las zonas se expanden sólo lo necesario para rellenar el espacio sobrante. Sin embargo habrá que tener en cuenta las dimensiones preferentes que se han indicado al crear el objeto (setPreferredSize).

El constructor de la clase BorderLayout nos permite especificar la distancia en pixels entre cada componente:

public BorderLayout(int hgap, int vgap) Adicionalmente, nos permite establecer esas distancias mediantes los métodos

setHgap(int) o setVgap(int). En el siguiente segmento de código se indica que posicione los controles entre sí con 5 pixels de separación.

Container pane= getContentPane(); this.setLayout(new BorderLayout(5,5)); JButton button = new JButton("Button 1 (PAGE_START)"); ···

Siendo el resultado el siguiente:

Page 21: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

21 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

BoxLayout Este layout permite apilar los componentes uno sobre otro, o posicionarles en una fila.

Se puede pensar que es igual a un FlowLayout, pero con mayor funcionalidad. Este Layout es muy útil cuando queremos diseñar barras de herramientas o barras verticales de botones ya que distribuye los componentes en una sola fila o columna (es decir: ubicar los componentes de manera horizontal o vertical). A continuación se incluye un código:

public MiBoxLayout() { super.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JPanel panelVertical = new JPanel(); panelVertical.setLayout(new BoxLayout(panelVertical, BoxLayout.Y_AXIS)); for (int i=0;i<3;i++) panelVertical.add(new JButton("Boton V.: " + i)); JPanel panelhorizontal = new JPanel(); panelhorizontal.setLayout(new BoxLayout(panelhorizontal, BoxLayout.X_AXIS)); for (int i=0;i<5; i++) panelhorizontal.add(new JButton("Boton H.: " + i)); getContentPane().add(panelhorizontal, BorderLayout.EAST); getContentPane().add(panelVertical, BorderLayout.SOUTH); this.pack(); }

La interfaz que genera el anterior código es el siguiente:

Para simplificar las cosas, BoxLayout usa un contenedor nativo llamado Box. Este contenedor permite crear las posiciones verticales u horizontales de posicionamiento.

public MiBoxLayout() {

Page 22: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

22 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

super.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); /* JPanel panelVertical = new JPanel(); panelVertical.setLayout(new BoxLayout(panelVertical, BoxLayout.Y_AXIS)); for (int i=0;i<3;i++) panelVertical.add(new JButton("Boton V.: " + i)); JPanel panelhorizontal = new JPanel(); panelhorizontal.setLayout(new BoxLayout(panelhorizontal, BoxLayout.X_AXIS)); for (int i=0;i<5; i++) panelhorizontal.add(new JButton("Boton H.: " + i)); getContentPane().add(panelhorizontal, BorderLayout.EAST); getContentPane().add(panelVertical, BorderLayout.SOUTH); this.pack(); */ Box bv = Box.createVerticalBox(); for (int i=0;i<5;i++) bv.add(new JButton("Botón V: " + i)); Box bh = Box.createHorizontalBox(); for (int i=0;i<3;i++) bh.add(new JButton("Boton H.:" + i)); getContentPane().add(bv, BorderLayout.EAST); getContentPane().add(bh, BorderLayout.SOUTH); this.pack(); }

El resultado generado es el siguiente:

FlowLayout El gestor de contenido FlowLayout permite hacer fluir los componentes del formulario

de izquierda a derecha hasta que se llena el espacio superior. Una vez ocupado ese espacio, incluye una nueva fila y continúa introduciendo componentes. Si el contenedor es suficientemente ancho para albergar los componentes, FlowLayout centra el contenido. Podemos incluso indicar al FlowLayout la manera de alinear los componentes (izquierda o derecha) mediante su constructor.

Page 23: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

23 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

public miFlowLayout() { super.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JPanel pan = new JPanel(new FlowLayout(FlowLayout.TRAILING)); pan.add(new JButton("1")); pan.add(new JButton("2")); pan.add(new JButton("Tres")); pan.add(new JButton("Cuatro")); //Posicionar los controles de Derecha a izquierda //En orden inverso a como se han ido agregando pan.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); getContentPane().add(pan); this.pack(); }

Cuando se establece al panel un FlowLayout, se puede establecer la orientación de la que se habla anteriormente. En el caso de un FlowLayout se pueden usar los siguientes:

- LEFT: Ancla los controles a la izquierda - CENTER: Centra todos los controles - RIGHT: Ancla los controles a la derecha - LEADING: La que indique la orientación de los componentes - TRAILING: Contraria a la que indica la orientación

Comentar por último, que con este gestor de interfaz también se pueden indicar los pixeles de separación entre cada componente, tanto de manera horizontal como de manera vertical.

CardLayout El administrador CardLayout se utiliza para posicionar componentes que usan el

mismo espacio visual. Sin embargo, esta funcionalidad ha sido trasladada al componente TabbedPane por lo que se omite el funcionamiento de este administrador.

GridBagLayout GridBagLayout es uno de los administradores de posición más flexibles que posee Java.

Permite posiciones componentes al estilo de una celda: es decir: mediante filas y columnas, permitiendo especificar los componentes que ocupan múltiples filas y/o columnas. Las filas o columnas no tienen porque ocupar el mismo ancho o alto. La siguiente figura, muestra la celda que se ha diseñado para generar la interfaz. Se puede ver como el botón de la segunda fila ocupa todas las columnas. De forma muy parecida, el botón de la tercera fila, ocupa las dos últimas columnas.

Page 24: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

24 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Se usa un objeto GridBagConstraints para indicar el comportamiento de los componentes en el GrdBagLayout. Cada componente administrador en un GridBagLayout está asociado a una instancia de GridBagConstraints, que como se ha comentado en líneas anteriores, especifica como posicionar el componente y el área del componente que debe localizarse en la celda. Además considera el tamañao mínimo y preferido de muestreo del componente. Se pueden especificar las siguientes restricciones (constraints):

- gridx,gridy: especifican la fila y columna de la parte superior izquierda del componente. La columna de la izquierda tiene direcciones gridx=0 y la fila superior gridy=0. Se puede usar la constraint GridBagConstraints.RELATIVE para especificar que el componente debe ser posicionad justo a la derecha o debajo del componentes que fue añadido anteriormente.

- gridwidth, gridheight: especifican el número de columnas o filas en el área de muestreo de los componentes. Es decir: especifica el número de celdas que el componente usará, El valor por defecto es 1. Se usa GridBagConstraints.REMAINDER para especificar que el componente sea el último de la fila o columna. GridBagConstraints.RELATIVE para especificar que el componente sea el siguiente al último de la fila o columna.

- fill: usado cuando el área del componente es mayor que el tamaño requerido por el componente para determinar cómo redimensionarse. GridBagConstraints.HORIZONTAL: hace al componente suficientemente ancho para rellenar el área horizontal. VERTICAL, hace al componente suficientemente alto para rellenar su espacio vertical. BOTH, rellena su área tanto en horizontal como en vertical.

- ipadx, ipady: especifica el relleno interno del componente. Cuando añadir al tamaño del componente. Por defecto 0.

- insets: especifica el relleno externo, o el espacio entre componentes y los bordes de visualización.

- anchor: usado cuando el componente es más pequeño que el área de visualización para determinar donde posicionar el componente. Las posibilidades son las siguientes:

------------------------------------------------- |FIRST_LINE_START PAGE_START FIRST_LINE_END| | | | | |LINE_START CENTER LINE_END| | | | | |LAST_LINE_START PAGE_END LAST_LINE_END| -------------------------------------------------

Page 25: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

25 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

- weightx,weighty: Se usa para especificar la distribución del espacio entre columnas y filas. Es importante a la hora de producirse cambios en el tamaño del contenedor. Si no se especifica un valor, todos los componentes se agrupan en el centro de su recipiente (valor 0,0). Estos weights (pesos) se especifican mediante valores entre 0 y 1. Un número alto indica que la fila o columna del componente debe adquirir más espacio.

Veamos el ejemplo anteriormente expuesto:

public miGridBagLayout() { super("GridBagLayout"); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); GridBagConstraints c = new GridBagConstraints(); setLayout(new GridBagLayout()); Container pan = getContentPane(); JButton btn = null; btn = new JButton("Botón 1"); //Usar un GridBagLayout para el botón c.fill = GridBagConstraints.BOTH; //Colocarle en la fila:0 columna:0 c.gridx=0; c.gridy=0; pan.add(btn, c); //---------- btn = new JButton("Boton 2"); c.fill = GridBagConstraints.HORIZONTAL; c.weightx=0.5; c.gridx=1; c.gridy=0; pan.add(btn, c); //-------- btn = new JButton("Botón 3"); c.fill= GridBagConstraints.HORIZONTAL; c.weightx=0.5; c.gridx=2; c.gridy=0; pan.add(btn,c); //--------- btn = new JButton("Botón 4"); c.fill=GridBagConstraints.HORIZONTAL; c.gridwidth=3; c.weighty=1; c.ipady=90;//Dar tamaño al componente c.gridx=0; c.gridy=1; pan.add(btn,c); //------- btn = new JButton("Botón 5"); c.fill = GridBagConstraints.HORIZONTAL; c.ipady=0; c.weighty=1; c.anchor = GridBagConstraints.PAGE_END; c.gridx = 1; c.gridwidth=2; c.gridy=2; pan.add(btn, c); this.pack();

Page 26: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

26 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

}

GridLayout GridLayout posiciona los componentes en una rejilla. Cada componente, se posiciona

en una celda que además son todas del mismo tamaño. Cuando se llama al constructor de este objeto, se indica el número de filas, columnas y la distancia entre cada componente. Igualmente, se pueden utilizar los métodos setHgap, setVgap, setRows, setColumns para establecer las propiedades de este componente, A continuación se muestra un ejemplo sencillo:

public miGridLayout() { super.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); Container pan = getContentPane(); //Creamos una rejilla de 4 filas y 3 columnas pan.setLayout(new GridLayout(4, 3, 2, 2)); for (int i=0;i<=9;i++) { JButton btn = new JButton(String.valueOf(i)); pan.add(btn); } this.pack(); }

La interfaz que se genera es la siguiente:

Posicionamiento Absoluto Java permite realizar un posicionamiento absoluto de los componentes, aunque lo

desaconseja. Para posicionar absolutamente controles en un contenedor, los haremos de la siguiente manera:

- Estableceremos el layout del contenedor a null. - Llamaremos al método setbounds del componente. - Llamaremos al método repaint del componente.

Debemos tener en cuenta que si se crean posicionamientos absolutos, los controles no se redimensionarán cuando la pantalla contenedora lo haga.

Page 27: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

27 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Componentes Textuales Existen varios componentes textuales en Swing, cada uno de ellos dedicado a una

funcionalidad específica que está agrupados en tres grupos. Estos son los siguientes:

- Controles de Texto: Sólo muestran una línea, y son capaces de generar eventos. Se utiliza para mostrar una pequeña cantidad de información al usuario.

- JTextArea: muestra varias líneas de texto, con el mismo formato (fuente). Se puede utilizar para permitir al usuario introducir una cantidad de texto mayor sin formato.

- Áreas Textuales Formateadas: permite mostrar texto formateado en varias líneas e incluso incrustar contenido multimedia. Pueden incluso se inicializados desde una URL.

A continuación se ven cada uno de estos componentes en profundidad.

JTextComponent Es la clase principal de componentes textuales. Proporciona las siguientes

características a sus clases hijas:

- Un modelo, llamado document que administra el contenido del componente. - Una view que muestra el componente en la pantalla - Un controller llamado editor kit que lee y escribe texto e implementa las opciones

de eventos. - Soporte para hacer y deshacer (undo y redo). - Listeners para navegación y cursores de edición.

A continuación se muestran las acciones más comunes con un objeto JTextComponent:

http://java.sun.com/docs/books/tutorial/uiswing/components/textapi.html

JTextField JTextField es un control de texto básico que permite al usuario introducir o ver una

cantidad pequeña de texto en una única línea. Cuando el usuario presiona la tecla enter el componente lanza el evento de acción.

Page 28: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

28 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JTextField txtnom = null; public misTextos() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new GridLayout(1, 2)); Container pan = getContentPane(); pan.add(new JLabel("Nombre")); txtnom = new JTextField("Introduce tú nombre"); txtnom.addActionListener(this); pan.add(txtnom); this.pack(); }

Vamos a ver ahora un ejemplo en el que mediante un JTextField marcamos una serie de caracteres de un color. Para ello hay que usar la interfaz Highlighter y HighlighterPainter.

public void actionPerformed(ActionEvent e) { ··· else { Highlighter h = new DefaultHighlighter(); txtnom.setHighlighter(h); try { //Seleccionar desde la posición 2 hasta la 8 (un total de 6 caracteres) // y seleccionamelo en color gris h.addHighlight(2, 8, new DefaultHighlighter.DefaultHighlightPainter(Color.GRAY)); } catch (BadLocationException ex) { Logger.getLogger(misTextos.class.getName()).log(Level.SEVERE, null, ex); } } }

Las acciones habituales con este componente son:

get|setText();get|setColumns();set|getHorizontalAlignment(); addActionListener(); set|isEditable();

JPasswordField Proporciona una caja de texto especializada para introducir contraseñas, que además

no muestra los caracteres pulsados. Estos caracteres se almacenan en un array de caracteres, y es capaz de lanzar un evento cuando el usuario presiona la tecla enter.

public class Passwords extends JFrame implements ActionListener { JPasswordField txtpass = null; public Passwords() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new GridLayout(1, 2)); txtpass = new JPasswordField("Contraseña", 12); txtpass.setActionCommand("pass"); txtpass.addActionListener(this);

Page 29: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

29 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

getContentPane().add(txtpass); JButton btn = new JButton("OK"); btn.addActionListener(this); btn.setActionCommand("ok"); getContentPane().add(btn); pack(); } public void actionPerformed(ActionEvent e) { JDialog d =null; if (e.getActionCommand().equals("pass")) { d= new JDialog(this, "Pass"); d.add(new JLabel("Acabaste.")); d.setLocationByPlatform(true); } else if (e.getActionCommand().equals("ok")) { d = new JDialog(this, "Contraseña"); d.getContentPane().add(new JLabel("La contraseña es: " + String.valueOf(txtpass.getPassword()))); } d.setModal(true); d.pack(); d.setVisible(true); } }

JFormattedTextField Nos permite especificar cuáles son los caracteres válidos a la hora de introducir

información por parte del usuario. JFormattedTextField añade un formateador y un objeto value.

El formateador nos permite configurar el campo textual a números, fechas en un formato localizable. Además, nos va a permitir especificar una máscara para determinar el tipo y la posición de cada carácter.

El constructor usado para crear un objeto de texto con formato necesita un objeto de tipo Format. Esto objeto se usa para traducir el valor del campo a texto y viceversa.

Se debe tener en cuenta que cuando trabajamos con un objeto JFormattedText, la propiedad text y value son diferentes. La propiedad text refleja lo que el campo está mostrando en ese momento (texto formateado), mientras que value representa un object. Cuando queramos recuperar recuperar el texto del componente llamaremos al método getText() mientras que si queremos recuperar su valor usaremos el método getValue().

Existen formateadores ya definidos que heredan directamente de la clase Format, como por ejemplo:

- DateFormatter: Destinado a fecha. La clase que permite obtener una instancia se llama DateFormat

- NumberFormatter. Números. NumberFormat - DecimalFormatter

Page 30: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

30 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Igualmente, se pueden crear máscaras de entrada (una máscara obliga al usuario a introducir en una posición concreta del componente un carácter o un grupo de caracteres. Por ejemplo: un NIF siempre son 8 dígitos y una letra). Para ello se utiliza la clase MaskFormatter. Este objeto recibe como una cadena la máscara para formatear el componente JFormattedTextField. La cadena tiene que estar formada por los siguientes caracteres:

Caracter Descripción

# Un dígito

' Caracter de escape

U Un caracter que se transforma a mayúsculas

L Un character que se transforma a minúsculas

A Representa un caracter o un número

? Cualquier carácter

* Cualquier cosa

H Un valor hexadecimal(0-9, a-f o A-F).

Adicionalmente, se pueden restringir la entrada de datos a ciertos caracteres. Es decir: si usáramos una máscara de entrada del tipo ’*’podríamos además limitar los caracteres que puede introducir. Veamos un ejemplo para aclarar los conceptos introducidos

public Formatos() throws ParseException { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new GridLayout(4, 2)); JLabel lbl = new JLabel("Numero"); NumberFormat nf = NumberFormat.getInstance(); //Un sólo dígito en la parte decimal nf.setMinimumFractionDigits(1); nf.setMaximumFractionDigits(1); JFormattedTextField txtnum = new JFormattedTextField(nf); getContentPane().add(lbl); getContentPane().add(txtnum); //Si no establecemos un valor inicial, cuando el usuario introduzca un valor //incorrecto ese valor permanece. txtnum.setValue(0); //------- Moneda getContentPane().add(new JLabel("Moneda")); NumberFormat formatoMoneda = NumberFormat.getCurrencyInstance(Locale.getDefault()); JFormattedTextField txtmon = new JFormattedTextField(); txtmon.setValue(0); getContentPane().add(txtmon); //------ Mascara getContentPane().add(new JLabel("Un DNI")); MaskFormatter mascaraDNI = new MaskFormatter("########-?"); JFormattedTextField txtdni = new JFormattedTextField(mascaraDNI); getContentPane().add(txtdni); //----- Fechas

Page 31: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

31 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

getContentPane().add(new JLabel("Una Fecha")); DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT); JFormattedTextField txtfecha = new JFormattedTextField(df); getContentPane().add(txtfecha); pack(); }

JEditorPane y JTextPane Los últimos controles que permiten mostrar información textual al usuario son

JEditorPane y JTextPane. Ámbos controles permiten cargar información desde una URL, sin embargo, mientras JEditorPane puede recibir una cadena en HTML, JTextPane necesita un objeto que le indique el estilo del texto a mostrar. Se aconseja ampliar estos componentes en la página oficial de Java.

Veamos un ejemplo de su uso.

public miJTextyEditor() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new GridLayout(1,2)); getContentPane().add(new JLabel("JEditorPane")); JEditorPane txte = new JEditorPane("text/html", "<HTML><B>Texto</B> con <I>formato</I></HTML>"); getContentPane().add(txte); pack(); }

AbstractButton AbstractButton representa la clase base de varios controles Swing. De esta clase

heredan directamente JButton, JMenuItem y JToggleButton.

Tiene diversos métodos de gran utilidad muchos de ellos presentes también en otras arquitecturas muy conocidas:

- doClick();; - doClick(int p); - addActionListener(); - setActionCommand(String s);getActionCommand(); - setEnabled(boolean b); - setSelected(boolean b); - setIcon(Icon i); getIcon() - setText(String l); getText() - setMnemonic(char c); - setPressedIcon(Icon i); - setDisabledIcon(Icon); getDisabledIcon();

La jerarquía de clases es la siguiente:

Page 32: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

32 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Como en otras ocasiones veremos el uso de cada una de estas clases.

JButton El objeto botón de Swing es capaz de mostrar tanto texto como imagen en su

contenido. Incluso permite posicionar el texto o la imagen en diferente posición.

Un JButton puede ser activado por el usuario de dos formas diferentes. Una de ellas es pulsándole y otra es usar el mnemónico que tenga asociado el texto. Este mnemónico suele ser un carácter que permite activarse con el teclado. Sin embargo, debemos tener en cuenta que el botón puede estar activado o no. En caso de no estarlo, el L&F se encargará de mostrar en la interfaz esta característica.

El control de los eventos sobre un botón se hará implementando la interfaz ActionListener, sin embargo, cuando trabajemos con un objeto JCheckBox, implementaremos ItemListener que nos permite saber si el checkox está activado o desactivado.

Veamos un ejemplo para comprobar las características de JButton:

public class Botones extends JFrame { public Botones() { this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new GridLayout(2, 1)); ImageIcon imgico = new ImageIcon(Botones.class.getResource("reglas.gif")); JButton btn1 = new JButton("Boton1",imgico); btn1.setVerticalTextPosition(SwingConstants.TOP); //TOP | BOTTOM | CENTER btn1.setIconTextGap(10); //Distancia entre la imagen y el texto // LEFT | RIGHT |CENTER | LEADDING | TRAILING btn1.setHorizontalTextPosition(SwingConstants.LEFT); btn1.setMnemonic(KeyEvent.VK_B); btn1.setToolTipText("Pincha aqui"); this.getContentPane().add(btn1); JButton btn2 = new JButton("Boton2"); btn2.setMnemonic(KeyEvent.VK_O); btn2.setEnabled(false); getContentPane().add(btn2); pack(); } }

AbstractButton

JButton JMenuItem JToggleButton

JCheckBoxMenuItem JRadioButtonMenuItem JCheckBox JRadioButton

Page 33: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

33 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

El anterior código generaría una imagen como la siguiente:

JToggleButton Es una clase que proporciona funcionalidad para aquellos botones que necesiten dos

estados, como por ejemplo JRadioButton y JCheckBox.

Esta clase se puede usar con total normalidad, cuando necesitemos mostrar botones con dos estados: Presionado o No Presionado. Se muestra un ejemplo sencillo, con el cambio de interfaz al presionar el botón:

public class Toggle extends JFrame { public Toggle() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); getContentPane().add(new JToggleButton("Hola")); pack(); } }

Sus apariencias serían las siguientes: Boton sin estar presionado, y Estando Presionado respectivamente.

JCheckBox Proporciona utilidad para introducir botones de selección en un JFrame. Se diferencian

de un JRadioButton en que permiten seleccionar varias opciones, mientras que JRadioButton sólo permiten seleccionar una opción.

Recordemos que para controlar la pulsación de cada uno de los elementos debemos implementar la interfaz ItemListener. Para activar un elemento usaremos el método setSelected(boolean b). Si quisiéramos obtener el estado del objeto, llamaríamos al método isSelected().

public class Checks extends JFrame implements ItemListener { public Checks() {

Page 34: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

34 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new GridLayout(1,1)); JCheckBox chk1 = new JCheckBox("Opcion1"); JCheckBox chk2 = new JCheckBox("Opcion2"); chk1.setMnemonic(KeyEvent.VK_O); getContentPane().add(chk1); getContentPane().add(chk2); chk1.addItemListener(this); chk2.addItemListener(this); pack(); } public void itemStateChanged(ItemEvent e) { JDialog jd = new JDialog(this, "Opciones"); jd.getContentPane().add(new JLabel(e.getItemSelectable().toString())); jd.pack(); jd.setVisible(true); } }

JRadioButton Los JRadioButton o también conocidos como OptionButton, son botones en los que

por convención sólo se puede seleccionar un elemento a la vez. En Swing, esto se hace, como la clase JRadioButton, pero además es necesario utilizar la clase ButtonGroup. Esta última clase permite controlar la agrupación de varios objetos JRadioButton. Además se puede utilizar también con la clase JCheckBox. (Realmente se puede utilizar con cualquier clase que herede de AbstractButton). La única funcionalidad que aporta es que sólo permite seleccionar un único objeto de tipo CheckBox.

Al igual que sucede con la clase JCheckBox, si necesitamos controlar la pulsación de algún, podemos implementar la interfaz ItemListener. En cambio, la funcionalidad que proporciona no es suficiente, y en el caso de los RadioButton debemos implementar la interfaz ActionListener. Veamos un ejemplo sencillo muy similar a otro encontrado en la página de Sun, donde se implementan las dos interfaces. Sería interesante probarlas:

public class Radio extends JFrame implements ItemListener, ActionListener { JLabel lbl = null; JRadioButton rd1 = null; JRadioButton rd2 = null; public Radio() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new BorderLayout()); JPanel pan = new JPanel(new GridLayout(1, 1)); lbl = new JLabel(); ButtonGroup bg = new ButtonGroup(); rd1 = new JRadioButton("Opcion1"); rd2 = new JRadioButton("Opcion2"); pan.add(rd1); rd1.setSelected(true);

Page 35: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

35 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

pan.add(rd2); bg.add(rd1); bg.add(rd2); getContentPane().add(pan,BorderLayout.LINE_START); rd1.addItemListener(this); rd2.addItemListener(this); rd1.addActionListener(this); rd2.addActionListener(this); pack(); } public void itemStateChanged(ItemEvent e) { //Descomentar este codigo para ver el resultado funcional if (e.getSource()==rd1) System.out.println(e.getSource().toString()); else System.out.println(e.getSource().toString());*/ } public void actionPerformed(ActionEvent e) { if (e.getSource()==rd1) System.out.println(e.getSource().toString()); else System.out.println(e.getSource().toString()); } }

JCheckBoxMenuItem y JRadioButtonMenuItem Estas dos clases las veremos junto con las clases de creación de menús.

Listas Como en muchas otras arquitecturas, existen varias tipos de listas que se pueden

utilizar. En Swing existen dos: JComboBox y JList. La diferencia fundamental entre ambas es la apariencia, la forma que tienen de mostrar la información, y la edición o no de la información por parte del usuario.

JComboBox Con este componente de lista, permitimos al usuario elegir un elemento entre varias

opciones.

Este componente, posee dos tipos de apariencia

- No Editable.

- Editable.

Page 36: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

36 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Los cuadros de lista, como se vio en el tema de introducción de Interfaces de usuario son enormemente útiles a la hora de reducir los errores de los usuarios.

Los métodos más interesantes pueden ser:

- addItem(Object o); - insertItemAt(Object o, int i); - Object getItemAt(int i); - getSelectedItem(); - removeAllItems(); - removeItemAt(int i); - getItemCount(); - setEditable(Boolean b);

Como en otros componentes, veamos como agregar elementos, manejar los eventos y alguna opción de interés.

public class Listas extends JFrame implements ActionListener, ItemListener { public Listas() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER)); JComboBox cmb = new JComboBox(); //Agregar opciones textuales cmb.addItem("Elemento 1"); cmb.addItem("Elemento 2"); cmb.addItem("Elemento 3"); cmb.addItem("Elemento 4"); //Seleccionar el 2º elemento. Desde 0 a n-1 cmb.setSelectedIndex(1); //Se produce el evento cuando se cambien elementos cmb.addActionListener(this); cmb.addItemListener(this); getContentPane().add(cmb); pack(); } public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(this,"Se ha pulsado el elemento " + ((JComboBox)e.getSource()).getSelectedItem().toString()); } public void itemStateChanged(ItemEvent e) { JOptionPane.showMessageDialog(this,"Se ha cambiado un elemento."); }

Page 37: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

37 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

}

El ejemplo anterior, representa un JComboBox no editable. A continuación se muestra el código para generar un Combo editable

public class Listas extends JFrame implements ActionListener, ItemListener { public Listas() { ········· JComboBox cmbe = new JComboBox(); cmbe.setEditable(true); cmbe.addItem("Opcion 1"); ·········· } }

JList Una lista nos permite mostrar al usuario una serie de elementos. Normalmente se

mostrarán en una o varias columnas. Cuando la lista no puede mostrar todos los elementos que posee, mostrará al usuario una barra de desplazamiento para poder mostrar el resto de opciones.

Para manejar los eventos en un objeto JList podemos implementar la interfazListSelectionListener.

Repasemos los métodos más interesantes:

- int getSelectedIndex(); - Object getSelectedValue() - clearSelection(); - boolean isSelectedIndex(int i)

public class Listas extends JFrame implements ListSelectionListener { public Listas() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER)); JList lst = new JList(new Object[]{"Opcion 1","Opcion 2","Opcion 3","Opcion 4", "Opcion 5","Opcion 6", "Opcion 7", "Opcion 8", "Opcion 9"}); lst.setLayoutOrientation(JList.HORIZONTAL_WRAP); //Gestor de Eventos lst.addListSelectionListener(this); getContentPane().add(lst); pack(); } public void valueChanged(ListSelectionEvent e) {

Page 38: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

38 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JOptionPane.showMessageDialog(this, ((JList)e.getSource()).getSelectedValue()); } }

El resultado obtenido sería el siguiente:

Como se ve en el ejemplo anterior, la lista de opciones de una lista, se deben incluir en su constructor, y debe ser un array de Object.

Etiquetas. JLabel Las etiquetas nos permiten mostrar al usuario información textual no editable. En

general suelen informar al usuario sobre algún campo de texto, o simplemente informan al usuario sobre algo. En Swing usaremos la clase JLabel, el cual nos permite incluir una imagen y un texto. Este texto, puede ser un código en HTML permitiendo de esta manera formatearse.

Los métodos más usados pueden ser:

- String getText(); - setText(String s); - setIcon(Icon i), - Icon getIcon();

A continuación veamos un ejemplo simple para manejar las etiquetas.

public class Etiquetas extends JFrame { public Etiquetas() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JLabel lbl = new JLabel(); JLabel lbl2 = new JLabel(); JLabel lbl3 = new JLabel(); setLayout(null); lbl.setBounds(10, 10, 100, 15); lbl.setText("Nombre "); lbl.setOpaque(true); lbl.setBackground(Color.red); lbl2.setText("<html><B>Nombre</B> <I>Formateado</I</html>"); lbl2.setOpaque(true); lbl2.setBounds(10, 25, 190, 15); lbl3.setText("Etiqueta con Imagen");

Page 39: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

39 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

ImageIcon img = new ImageIcon(Etiquetas.class.getResource("reglas.gif")); lbl3.setIcon(img); lbl3.setBounds(10,40,190,15); getContentPane().add(lbl); getContentPane().add(lbl2); getContentPane().add(lbl3); this.setSize(300, 200); } }

El aspecto que obtendríamos sería el siguiente:

Spinners. Los spinners son parecidos a las listas con la diferencia de que un spinner no despliega

el conjunto de opciones que posee. Un clásico spinner es la configuración del relof de Windows, que divide la hora los minutos y los segundos y nos permite incrementar o reducir el valor. Este control en otros entornos se suele llamar NumericUpDownControl.

Spinner utiliza la interfaz SpinnerModel para mostrar los elementos que va a contener. Swing ya posee varias clases que implementan esta interfaz como por ejemplo SpinnerNumberModel, SpinnerDateModel o SpinnerListModel, para mostrar números, fechas o elementos de un array respectivamente. Spinner permite modificar el formato con el que se muestra la información mediante las clases JSpinner.NumberEditor y JSpinner.DateEditor. Con el método setEditor podríamos establecer el formato concreto. Evidentemente, nosotros también podemos crear nuestro propio formateador.

Cuando usamos un modelo de tipo SpinnerNumberModel podremos establecer los valores mínimos, máximos e incremento del control.

Para controlar el cambio de valor del objeto Spinner, usaremos la interfaz ChangeListener.

A continuación vemos un ejemplo de uso de este componente.

public class NumericUpDown extends JFrame implements ChangeListener { public NumericUpDown() {

Page 40: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

40 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER)); SpinnerListModel sl = new SpinnerListModel(new Object[]{"Opcion1", "Opcion2","Opcion3","Opcion4","Opcion5"}); JSpinner js = new JSpinner(sl); SpinnerNumberModel sn = new SpinnerNumberModel(0, 0, 10, 2); JSpinner jsn = new JSpinner(sn); SpinnerDateModel sd = new SpinnerDateModel( Calendar.getInstance().getTime(),null,null,Calendar.YEAR); JSpinner jsd = new JSpinner(sd); //Cambiamos el editor para que nos muetre la información de diferente manera jsd.setEditor(new JSpinner.DateEditor(jsd, "dd/MM/yyyy")); getContentPane().add(js); getContentPane().add(jsn); getContentPane().add(jsd); js.addChangeListener(this); jsn.addChangeListener(this); jsd.addChangeListener(this); pack(); } public void stateChanged(ChangeEvent e) { JOptionPane.showMessageDialog(this, ((JSpinner)e.getSource()).getValue().toString()); } }

Uso de Menús Los menús proporcionan una manera muy útil de proporcionar al usuario una lista de

opciones, tanto de operación como de acción.

Los menús, por convención se sitúan en una barra de menús o en un menú contextual también conocidos como popupmenus Una barra de menús puede contener uno o más menús o submenús que inicialmente son invisibles para el usuario hasta que este realiza alguna acción. Este popupmenu generalmente aparece en la posición del cursor.

La jerarquía de clases es la siguiente:

JComponent

JMenuBar JPopupMenu JSeparatrorJAbstractButton

JMenuItem

JMenu JCheckBoxMenuItem JRadioButtonMenuItem

Page 41: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

41 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Como se puede apreciar, los elementos de menús (menú ítems) son meramente botones puesto que heredan directamente de JActractButton. Este comportamiento es posible porque cuando se activa un menú automáticamente se muestra un popup menú que muestra los elementos.

Creación de Menús Habituales Debemos tener en cuenta que para crear menús es suficiente con conocer la clase

JMenuBar, que representa una barra donde se van a localizar los JMenu, JMenu que representa una opción principal de la barra de menús, y JMenuItem, que representa cada una de las opciones que posee un menú. Estas opciones pueden ser JCheckBoxMenuItem y/o JRadioButonMenuItem, a las cuales se las puede agregar una imagen. Por lo tanto, cuando creemos un JMenuBar, debemos añadirle los JMenu que deseemos. A este JMenu, a su vez debemos agregarle los JMenuItem, y por último la barra de menús debemos añadirla al contenedor principal mediante el método setJMenuBar().

Normalmente, y por facilidad, se suelen dividir las opciones que se ofrecen al usuario con un separador. Para ello usamos el método addSeparator() de la clase JMenu.

Cuando necesitemos crear una opción de menú que contenga submenús, en vez de crear un objeto JMenuItem, debemos crearlo del tipo JMenu, como veremos más adelante.

Con la interfaz ActionListener (el método a implementar es actionPerformed) podemos capturar los eventos lanzados por un objeto JMenu, mientas que si necesitamos controlar el evento de elección de un objeto JRadioButtonMenuItem o JCheckBoxMenuItem debemos utilizar la interfaz ItemListener (cuyo método es itemStateChanged).

Al igual que sucede con otros componentes, se puede activar una opción de menú con un nemónico. Adicionalmente, los menús implementan un método para incluir lo que Java demonina aceleradores. Estos aceleradores proporcionan otro método de acceso rápido a las opciones de los menús, y dichas opciones aparecen junto al menú. Más adelante se verá un ejemplo completo donde se utilizan.

A continuación se incluye un código que genera un JFrame con un menú habitual:

public class unMenu extends JFrame implements ActionListener, ItemListener { JMenuBar barra = null; JMenu mnuArchivo = null; JMenuItem mnuiNuevo = null; JRadioButtonMenuItem mnuiUnRadio = null; JRadioButtonMenuItem mnuiOtroRadio = null; JCheckBoxMenuItem mnuiUnCheck = null; JMenu mnuiUnMenuConSubmenu = null; JMenuItem mnuiUnSubmenu = null; JMenuItem mnuiUnOtroSubmenu = null; public unMenu() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); barra = new JMenuBar(); mnuArchivo = new JMenu("Archivo"); mnuArchivo.setMnemonic(KeyEvent.VK_A); barra.add(mnuArchivo); mnuiNuevo = new JMenuItem("Nuevo");

Page 42: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

42 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

mnuiNuevo.addActionListener(this); mnuiNuevo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK)); mnuArchivo.add(mnuiNuevo); mnuArchivo.addSeparator(); mnuiUnRadio = new JRadioButtonMenuItem("Un Radio Button", false); mnuiUnRadio.addItemListener(this); mnuiOtroRadio = new JRadioButtonMenuItem("Otro", new ImageIcon(unMenu.class.getResource("reglas.gif"))); mnuArchivo.add(mnuiUnRadio); mnuArchivo.add(mnuiOtroRadio); mnuiUnCheck = new JCheckBoxMenuItem("Un Check", true); mnuiUnCheck.addItemListener(this); mnuArchivo.add(mnuiUnCheck); mnuiUnMenuConSubmenu = new JMenu("Un Menu con Submenu"); mnuiUnSubmenu = new JMenuItem("Una subopcion"); mnuiUnOtroSubmenu = new JMenuItem("Otro Submenu"); mnuiUnMenuConSubmenu.add(mnuiUnSubmenu); mnuiUnMenuConSubmenu.add(mnuiUnOtroSubmenu); mnuArchivo.add(mnuiUnMenuConSubmenu); this.setJMenuBar(barra); this.setSize(500, 350); } public void actionPerformed(ActionEvent e) { if (e.getSource() == mnuiNuevo) { JOptionPane.showMessageDialog(this, "Nuevo"); } } public void itemStateChanged(ItemEvent e) { if (e.getSource() instanceof JCheckBoxMenuItem) JOptionPane.showMessageDialog(this, ((JCheckBoxMenuItem) e.getSource()).getText()); else if (e.getSource() instanceof JRadioButtonMenuItem) JOptionPane.showMessageDialog(this, ((JRadioButtonMenuItem) e.getSource()).getText()); } }

El resultado que obtenemos es el siguiente:

Page 43: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

43 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Creación de Menús Contextuales Para poder mostrar un menú contextual (popup Menu) debemos registrar un

escuchador de evento en aquel componente sobre el cual se debe mostrar el menú. Normalmente, el evento a usar suele ser el botón derecho, y para ello implementamos la interfaz MouseListener. Sin embargo depende de la arquitectura. Es decir: si nos encontramos en un sistema Windows, normalmente se muestra el menú contextual con la opción anteriormente indicada, sin embargo, nos podemos encontrar con otro sistema en el que se puede mostrar el menú contextual de una forma diferente.

Veamos un ejemplo:

public class unMenuContextual extends JFrame implements MouseListener, ActionListener { JPopupMenu pop = null; public unMenuContextual() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new BorderLayout()); JTextArea txt = new JTextArea(); pop = new JPopupMenu(); txt.add(pop); JMenuItem mnui1 = new JMenuItem("Opcion 1"); JMenuItem mnui2 = new JMenuItem("Opcion 12"); pop.add(mnui1); mnui1.addActionListener(this); mnui2.addActionListener(this); pop.add(mnui2); txt.addMouseListener(this); getContentPane().add(txt,BorderLayout.CENTER); } public void mouseClicked(MouseEvent e) { if (e.isPopupTrigger()){ pop.setLocation(getMousePosition().x, getMousePosition().y); pop.setVisible(true); } } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void actionPerformed(ActionEvent e) { System.out.println("Algo se ha pulsado"); } }

Page 44: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

44 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Los Menús en Swing se pueden configurar prácticamente por completo. Se recomienda echar un vistazo a la API de Java para ampliar el conocimiento sobre ellos.

Barras de Botones. JToolBar JToolBar es un contenedor de varios botones, habitualmente en una fila o columna.

JToolBar permite que el usuario mueva en cualquier dirección de la ventana la barra de botones siempre y cuando JToolBar esté contenida en un administrador de posicionamiento de tipo BorderLayout, y establezcamos que la barra de botones es flotante con el método setFloteable.

Para controlar los eventos de los botones de una JToolBar debemos implementar la interfaz ActionListener.

Veamos un ejemplo:

public class BarraBotones extends JFrame implements ActionListener { JButton btn1 ; JButton btn2; JTextArea txt; public BarraBotones() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new BorderLayout(10, 10)); JToolBar barra = new JToolBar("General"); btn1 = new JButton(); btn2 = new JButton(); txt = new JTextArea(); this.setSize(new Dimension(400, 200)); barra.setFloatable(true); btn1.setToolTipText("Izquierda"); btn1.setActionCommand("Izda"); btn1.setIcon(new ImageIcon(BarraBotones.class.getResource("left.jpg"))); btn2.setIcon(new ImageIcon(BarraBotones.class.getResource("right.gif"))); btn2.setToolTipText("Derecha"); btn2.setActionCommand("Drch"); barra.add(btn1); barra.add(btn2); btn1.addActionListener(this); btn2.addActionListener(this); getContentPane().add(barra, BorderLayout.PAGE_START); getContentPane().add(txt, BorderLayout.CENTER); } public void actionPerformed(ActionEvent e) { txt.append("Has pulsado el botón: "); if (e.getActionCommand().equals("Izda")) { txt.append("Izquierda.\r\n"); }

Page 45: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

45 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

if (e.getActionCommand().equals("Drch")) { txt.append("Derecha.\r\n"); } } }

El JFrame que obtenemos es el siguiente:

El usuario, tal y como se ha comentado anteriormente, puede jugar con la barra de botones, puesto que puede colocarla en cualquier posición de la ventana e incluso sacarla fuera de ella. A pesar de ello, podemos indicarle la orientación de la barra de botones a través del método setOrientation (barra.setOrientation(JToolBar.VERTICAL);). Si establecemos esta propiedad a la barra, obtenemos el siguiente resultado:

JPanel. GroupBox Los paneles o cajas grupales se utilizan precisamente para agrupar conjunto de

componentes o controles. Resultan de gran utilidad para el usuario, puesto que permiten identificar información relacionada.

En Swing, JPanel es el componente que permite realizar las acciones comentadas anteriormente. JPanel es bastante configurable puesto que nos permite establecer colores de fondo para la agrupación, así como el pintado de todo el componente. Al igual que los contenedores principales, un JPanel al ser también un contenedor, tiene un administrador de posicionamiento.

Debido a la sencillez de este componente, vamos a ir directamente al ejemplo:

public class Paneles extends JFrame { public Paneles() { JPanel panSup = new JPanel(); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setSize(new Dimension(400, 250)); setResizable(false); setLayout(new BorderLayout());

Page 46: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

46 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

panSup.setLayout(new FlowLayout(FlowLayout.CENTER)); JLabel lbl = new JLabel("Nombre"); JTextField txt = new JTextField(20); panSup.add(lbl); panSup.add(txt); panSup.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); this.add(panSup, BorderLayout.PAGE_START); JPanel pantlfs = new JPanel(); pantlfs.setLayout(new FlowLayout()); JLabel lblt = new JLabel("Teléfono"); JTextField txtt = new JTextField(20); pantlfs.add(lblt); pantlfs.add(txtt); pantlfs.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); this.add(pantlfs, BorderLayout.PAGE_END); } }

El resultado sería el siguiente:

Cuadros de Diálogo3

Un cuadro de diálogo o son ventanas que muestran información de cualquier tipo al usuario. Este tipo de información suele ser: errores, información que debe tener en cuenta, etc., y son especialmente útiles para comunicarnos con el usuario.

En Java, la clase que implementa este comportamiento se denomina JOptionPane.

Todos los cuadros de diálogo deben pertenecer a un Frame, de tal forma que cuando el Frame se destruye, lo hacen también sus Frames. De la misma forma sucede si se minimizan o maximizan.

Los cuatros de diálogo por norma general son modales (bloquean la interacción del usuario obligando a seleccionar alguna opción en el diálogo). Si no deseamos este comportamiento deberemos utilizar la clase JDialog. Esta clase hereda directamente de la clase Dialog del paquete awt. Posee un contenedor principal, sobre el cual podemos incluir cualquier componente.

Nos centraremos en la clase JOptionPane. JOptionPane nos proporciona implementaciones para mostrar diferentes tipos de mensajes al usuario. Nos permite mostrar

3 Se recomienda ampliar la información de esta clase, en la página web de Java.

Page 47: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

47 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

mensajes con un texto concreto, un título, una imagen, y un grupo de botones de opción. Por defecto, JOptionPane proporciona una serie de iconos, dependientes del Look & Feel que estemos utilizando.

A continuación se resumen los tipos de mensajes que se pueden mostrar (a través de métodos estáticos de la clase JOptionPane):

Método Descripción showConfirmDialog Muestra un mensaje para que el usuario confirme alguna

posible acción. La opción del usuario la recuperamos a través del valor retornado por el método. Por ejemplo: ¿Está seguro que desea eliminar el archivo?

showInputDialog Muestra una ventana de mensaje para que el usuario escriba o selecciona algún elemento. La información que ha proporcionado el usuario se obtiene a través de la devolución del método como una cadena o un Object (dependiendo del método usado). Por ejemplo: Escriba su nombre

showMessageDialog Muestra un mensaje de información general al usuario. Por ejemplo: “La acción solicitada se ha realizado satisfactoriamente”.

showOptionDialog Muestra un mensaje con diferentes opciones al usuario, para que seleccione una de ellas. La opción del usuario, se obtiene mediante la devolución del método.

JOptionPane proporciona otro conjunto de métodos también estáticos usados cuando se muestren cuadros de diálogo contenidos en JInternalFrames.

La API proporciona diferentes parámetros para construir los cuadros de diálogos, según la sobrecarga que proporcionan los métodos, son los siguientes:

- message: El objeto a mostrar. La información que se aporta al usuario. - messageType: tipo de mensaje a mostrar, siendo posible los siguientes:

ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, PLAIN_MESSAGE.

- optionType: determina las opciones a mostrar en el panel de botones. Las posibles opciones son: DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION, OK_CANCEL_OPTION.

- icon: El icono a mostrar en el mensaje. - options: lista de opciones que se da al usuario (en un JList). - initialValue: elección inicial que se ofrece al usuario.

Veamos un ejemplo, en el que se incluyen los cuatro tipos de mensajes que se pueden mostrar:

public class Dialogos extends JFrame implements ActionListener { public Dialogos() {

Page 48: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

48 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JButton btn1 = new JButton("Botón 1"); JButton btn2 = new JButton("Botón 2"); JButton btn3 = new JButton("Botón 3"); JButton btn4 = new JButton("Botón 4"); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER)); btn1.setActionCommand("Boton1"); btn2.setActionCommand("Boton2"); btn3.setActionCommand("Boton3"); btn4.setActionCommand("Boton4"); btn1.addActionListener(this); btn2.addActionListener(this); btn3.addActionListener(this); btn4.addActionListener(this); getContentPane().add(btn1); getContentPane().add(btn2); getContentPane().add(btn3); getContentPane().add(btn4); pack(); } public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("Boton1")) { int v = JOptionPane.showConfirmDialog(this, "Hola", "Titulo", JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.WARNING_MESSAGE); System.out.println(v); } if (e.getActionCommand().equals("Boton2")) { String s =(String)JOptionPane.showInputDialog(this,"Mensaje","Titulo", JOptionPane.QUESTION_MESSAGE, null, new Object[]{"Uno","Dos"},"Uno"); System.out.println(s); } if (e.getActionCommand().equals("Boton3")) { JOptionPane.showMessageDialog(this, "La acción se ha llevado a cabo", "Titulo", JOptionPane.INFORMATION_MESSAGE, null); } if (e.getActionCommand().equals("Boton4")) { int v = JOptionPane.showOptionDialog(this, "Selecciona uno", "El Titulo", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE, null, new String[]{"Uno","Dos"}, null); System.out.println(v); } } }

El resultado de los cuadros de diálogo es el siguiente:

Page 49: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

49 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Diálogos Personalizados Como se ha comentado anteriormente, la clase JDialog nos permite crear nuestros

propios cuadros de diálogo.

Un ejemplo de su utilización sería el siguiente:

JDialog dialogo = new JDialog(this, "Un Mensaje",true); dialogo.getContentPane().add(new JButton("Un Boton")); dialogo.pack(); dialogo.setVisible(true);

File Choosers Los selectores de ficheros proporcionan una interfaz para navegar a través de un

sistema de ficheros, así como elegirlos, etc. La clase que representa este comportamiento se denomina JFileChooser. Esta clase nos permite mostrar una ventana modal que contiene el componente. Esta clase permite además, el directorio inicial donde se mostrarán los ficheros, así como un filtrado de los mismos (sólo ficheros txt, o sólo ficheros docx, etc.).

Cuando se utilizan estos componentes, el usuario debe permitir el escaneo del contenido del disco, solamente cuando se utiliza JavaWebStart

Un JFileChooser se puede mostrar con tres métodos diferentes:

- showOpenDialog(Component c). - showSaveDialog(Component c) - showDialog(Component c, String s).

En los dos primeros métodos, el componente recibe un parámetro de tipo component que determina el padre del JFileChooser. En el último caso, además de indicarle el padre del componente, nos permite especificar el contenido del botón de aprobación.

Una vez que el usuario, ha seleccionado un fichero, se pueden dar tres posibles casos:

- El usuario acepta la selección (pulsa sobre el botón de aprobación)

Page 50: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

50 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

- El usuario cancela la selección (pulsa sobre el botón de cancelación) - Se produce un error con el componente modal.

Para todos estos casos, JFileChooser, contienen unas constantes (enteras) que representan estas situaciones.

- JFileChooser.APPROVE_OPTION - JFileChooser.CANCEL_OPTION - JFileCHooser.ERROR_OPTION

Cuando queramos recuperar el fichero y/o el directorio usaremos el método getSelectedFile() o getSelectedFiles() en el caso que el usuario pueda seleccionar varios ficheros. Además podemos usar los métodos getPath(), isDirectory() o exists(), entre otros, para obtener información adicional sobre la selección del usuario.

Veamos varios ejemplos:

Permitir al usuario seleccionar un fichero:

JFileChooser f = new JFileChooser(); //JFileChooser.FILES_ONLY //JFileChooser.DIRECTORIES_ONLY //JFileChooser.FILES_AND_DIRECTORIES f.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); f.setFileFilter(new FileNameExtensionFilter("Ficheros de Texto", "txt", "dat")); f.setDialogTitle("Selecciona un fichero."); int v = f.showOpenDialog(this); if (v == JFileChooser.APPROVE_OPTION) { File fichero = f.getSelectedFile(); ··· }

La clase FileNameExtensionFilter es una implementación de la clase abstracta FileFilter.

El resultado que obtenemos es el siguiente:

Permitir al usuario guardar un fichero:

Page 51: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

51 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JFileChooser f = new JFileChooser(); f.setFileFilter(new FileNameExtensionFilter("Ficheros de Texto", "txt")); f.setDialogTitle("Introduzca el nombre del fichero a guardar"); int v = f.showSaveDialog(this); if (v == JFileChooser.APPROVE_OPTION) { File fichero = f.getSelectedFile(); Docs aux = (Docs) d.getSelectedFrame(); aux.guardarFichero(fichero); }

Y el resultado sería:

int v = f.showDialog(this, "Abre el fichero");

Por último, modificar el botón de aprobación del usuario:

Obtenemos el mismo comportamiento, pero con la siguiente interfaz (texto del botón

de aprobación, diferente):

Page 52: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

52 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Interfaces MDI. Internal Frames Como se vio en la introducción del tema, en general, existen dos tipos de aplicaciones:

SDI y MDI. Esta última conocida como interfaz de documento múltiple permite crear ventanas que contienen a otras. Las aplicaciones de gestión suelen tener este tipo de interfaz.

Para crear aplicaciones MDI, en Swing es necesario utilizar las clases JInternalFrames y JDesktopPane. Esta última clase será la contenedora de los InternalFrames.

Por convención cuando se utilicen JInternalFrames debemos tener en cuentas las siguientes cuestiones:

- Siempre debemos establecer el tamaño de los JInternalFrames - Es conveniente establecer la localización de los JInternalFrames - Los componentes de in JInternalFrame se añadirán siempre al contenedor principal - Los JInternalFrame siempre se añadirán al JDesktopPane - Los JInternalFrame se mostrarán con el método setVisible. - Los JInternalFrame lanzan eventos de tipo InternalFrameListener

JInternalFrame nos permite además cambiar su propia interfaz y comportamiento con los siguientes métodos:

- isCloseable();setCloseable(boolean b); - setResizable(boolean b);isResisable(); - setMaximizable(boolean b); - setIconifiable(boolean b); - show(); - toBack(); - toFront();

Veamos un ejemplo de implementación:

public class MDI extends JFrame implements InternalFrameListener { JDesktopPane d = new JDesktopPane(); public MDI() { super("Interfaz MDI"); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JInternalFrame frmin = new JInternalFrame("Doc 1"); frmin.addInternalFrameListener(this); frmin.setSize(300, 200); frmin.setVisible(true); frmin.setResizable(true); frmin.setMaximizable(true); d.add(frmin); add(d); this.setExtendedState(JFrame.MAXIMIZED_BOTH); } public void internalFrameOpened(InternalFrameEvent e) { System.out.println("Frame Abierto"); }

Page 53: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

53 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

public void internalFrameClosing(InternalFrameEvent e) { } public void internalFrameClosed(InternalFrameEvent e) { } public void internalFrameIconified(InternalFrameEvent e) { } public void internalFrameDeiconified(InternalFrameEvent e) { } public void internalFrameActivated(InternalFrameEvent e) { } public void internalFrameDeactivated(InternalFrameEvent e) { } }

El resultado que obtenemos es similar al siguiente:

JSplitPane JSplitPane es un componente que permite mostrar dos componentes en una zona

concreta de un contenedor, que permite ampliar o reducir el tamaño de ambos. Proporciona la utilidad similar a un explorador de Windows, donde la parte izquierda contiene las unidades del equipo y la parte derecha el contenido de cada unidad. La estructura de componentes que podemos crear puede ser la siguiente:

Page 54: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

54 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JSplitPane puede realizar la división de dos maneras: en horizontal o en vertical, que hay que determinar cuándo se instancia el objeto así como los contenedores de cada una de las partes divididas. Sin embargo, podemos utilizar los métodos setXXXComponent para establecer el componente en la izquierda, derecha, parte superior o inferior del componente.

Para que JSplitPane funcione correctamente es conveniente establecer el tamaño mínimo y el preferido de los componentes. De esta manera JSplitPane sabe cuántos pixeles puede moverse en una dirección u otra. A continuación se muestran algunos métodos que pueden resultar de utilidad para JSplitPane:

- setDividerSize(int): establece el ancho de JSplitPane (anchura/altura del divisor) - setOneTouchExpandable(boolean b): determina si el split se podrá expandir con un

click. Cuando se establece a true, el control muestra unas pequeñas flechitas para expandir de golpe los controles. En caso contrario, es una única barra.

A continuación se muestra un sencillo ejemplo, así como el resultado que obtendríamos:

public class Splitter extends JFrame { public Splitter() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JSplitPane div = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); JList lst = new JList(new String[]{"OPcion1","Opcion2","Opcion3", "Opcion4"}); lst.setMinimumSize(new Dimension(180, this.getSize().height)); JLabel lbl = new JLabel("Zona Derecha"); div.setLeftComponent(lst); div.setRightComponent(lbl); div.setDividerLocation(0.7); div.setOneTouchExpandable(true); div.setOpaque(false); getContentPane().add(div); setExtendedState(JFrame.MAXIMIZED_BOTH); } }

Page 55: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

55 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JSlider JSlider es un componente que proporciona una especie de barra de valores

desplazable. Puede representar una barra de volumen en una aplicación de reproducción de flujos de audio, o para aumentar o disminuir el tamaño de la letra en un editor de textos.

Cuando se instancia un objeto JSlider podemos establecer la orientación (horizontal o vertical) así como los valores máximos y mínimos que puede desplazarse. Adicionalmente, se puede instanciar el componente con un objeto de tipo BoundedRangeModel (una clase que implementa esta interfaz es DefaultDoundedRangeModel).

A continuación se comentan algunos métodos de utilidad para este componente:

- setPaintTicks(boolean b): método para indicarle al componente que dibuje las marcas de valores.

- setPaintLabels(boolean b):método para indicar al componente, que pinte el rango de valores. Para que ambos métodos funcionen correctamente, hay que llamar al método setMinorTickSpacing o setMajorTickSpacing.

- setFont(Font f): establece la fuente usada para mostrar los valore de la barra.

Podemos controlar el cambio de valor del componente JSlider implementando la interfaz ChangeListener. Esta interfaz proporciona el método stateChanged(ChangeEvent e) que debemos proporcionar el código necesario en aquella clase que implemente dicha interfaz. Posteriormente, usaremos el método addChangeListener de la clase JSlider para establecer el escuchador de esos eventos.

A continuación vemos un sencillo ejemplo de implementación de este componente:

Page 56: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

56 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

public class miSlider extends JFrame implements ChangeListener { JLabel lbl = null; public miSlider() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER)); lbl = new JLabel("Valor: "); //Orientación, Valor mínimo, Valor Máximo, Valor inicial JSlider js = new JSlider(JSlider.HORIZONTAL,0, 20, 0); js.setMinorTickSpacing(5); js.setMajorTickSpacing(5); js.setPaintLabels(true); js.setFont(new Font("Arial", Font.ITALIC, 8)); js.setPaintTicks(true); js.addChangeListener(this); getContentPane().add(lbl); getContentPane().add(js); setSize(300, 200); } public void stateChanged(ChangeEvent e) { lbl.setText("Valor: " + ((JSlider)e.getSource()).getValue()); } }

El resultado que obtenemos es el siguiente:

Cuando la barra de desplazamiento se mueva, mostrará el valor que tiene en ese momento, en el JLabel cuyo contenido inicial es Valor.

Nota: Se pueden cambiar los valores que muestra el componente, mediante el método setLabelTable. Para ello hay que proporciona un objeto de tipo Dictionary.

JTabbedPane JTabbedPane representa un componente de pestañas que permite incluir

componentes en cualquiera de ellas. Es muy útil cuando necesitamos mostrar mucha información al usuario que no es posible mostrar en toda la pantalla.

Page 57: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

57 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Puede parecer complicado el funcionamiento de este componente, pero resulta bastante sencillo. Cuando construimos un objeto de este tipo, es necesario indicar la orientación del componente (JTabbedPane.TOP, JTabbedPane.BOTTOM, JTabbedPane.LEFT, or JTabbedPane.RIGHT), y su comportamiento cuando el componente no pueda mostrar el texto de las pestañas (JTabbedPane.WRAP_TAB_LAYOUT, JTabbedPane.SCROLL_TAB_LAYOUT)

Para añadir o eliminar una pestaña usaremos el método addTab o remove respectivamente. Cuando usemos el método addTab en cualquier de sus sobrecargas, podemos establecer, el texto que muestra la pestaña, un icono significativo del contenido, un tooltip para ampliar información al usuario y el contenido que se debe mostrar cuando se active la pestaña.

Podemos controlar el cambio de una pestaña a otra mediante la interfaz ChangeListener.

Sin más dilación, veamos un sencillo ejemplo de utilización y el resultado que obtenemos.

public class Pestañas extends JFrame implements ChangeListener { public Pestañas() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JTabbedPane pesta = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT); pesta.addTab("Pestaña 1", new JLabel("Pestaña 1")); pesta.addTab("Pestaña 2", new JLabel("Pestaña 2")); pesta.addTab("Pestaña 3", null, new JButton("Algo"), "Una pestaña con un botón"); getContentPane().add(pesta); pesta.addChangeListener(this); setSize(210, 150); } public void stateChanged(ChangeEvent e) { } }

Page 58: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

58 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

JTree Con este componente podemos mostrar una interfaz vertical de tipo jerárquica o

arbórea. Proporciona una interfaz similar a un explorador de directorios del sistema Windows.

Una imagen de lo que puede representar es la siguiente:

Cada elemento, que se muestra en una única fila se denomina nodo que a su vez puede tener otros nodos hijos (también llamados ramas). Los nodos pueden estar expandidos o plegados (collapsed).

Para la creación de los nodos, debemos usar una clase que implemente la interfaz TreeNode, como puede ser la clase DefaultMutableTreeNode o DefaultTreeModel. Cuando se crea el objeto JTree es necesario pero no obligatorio indicarle el objeto TreeNode raíz, y a partir de este objeto, se indican los hijos de cada uno. Siempre hay que generar la estructura a partir del nodo raíz, y una vez que la tengamos generada, crear el JTree con el nodo principal.

Al igual que en otros componentes, podemos controlar los eventos del objeto JTree implementando la interfaz TreeSelectionListener, TreeExpansionListener y TreeWillExpandListener. Estas interfaces proporcionan los métodos void valueChanged(TreeSelectionEvent e); public void treeExpanded(TreeExpansionEvent event); y public void treeCollapsed(TreeExpansionEvent event); public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException; y public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException; respectivamente. Se lanza el método de la interfaz TreeSelectionListener cuando se selecciona un nodo diferente. Se lanza los métodos de TreeExpansionListener cuando se expande o plega un nodo, y finalmente se lanzan los métodos de TreeWillExpandListener antes de expandir o plegar un nodo.

La apariencia de este componente viene determinada por el Look & Feel que se haya establecido. Podemos cambiarle parte de la apariencia a través de pares clave-valor. Por ejemplo, para cambiar la apariencia de las líneas de referencia de los nodos, podemos hacerlo mediante el método tree.putClientProperty("JTree.lineStyle", "Horizontal"). Los posibles valores son: Horizontal, None, Angled.

A continuación se muestra el código así como el resultado que obtenernos:

public class Arbol extends JFrame implements TreeSelectionListener, TreeExpansionListener, TreeWillExpandListener { public Arbol() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER));

Page 59: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

59 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

//Instanciamos el raíz y le indicamos que puede tener hijos DefaultMutableTreeNode raiz = new DefaultMutableTreeNode("Raíz", true); //Agregamos al nodo raíz un nuevo hijo raiz.add(new DefaultMutableTreeNode("Hijo 1",true)); //Instanciamos un nuevo nodo DefaultMutableTreeNode hijo2 = new DefaultMutableTreeNode("Hijo 2", true); //Y le agregamos un subnodo hijo2.add(new DefaultMutableTreeNode("Sub Hijo de Hijo 2",false)); //Agregamos el Hijo 2 al nodo raíz raiz.add(hijo2); //Agregamos toda la estructura al nodo Raíz. JTree arb = new JTree(raiz,true); arb.setEditable(true); arb.putClientProperty("JTree.lineStyle", "Horizonal"); arb.addTreeExpansionListener(this); arb.addTreeSelectionListener(this); arb.addTreeWillExpandListener(this); getContentPane().add(arb); setSize(300, 250); } public void valueChanged(TreeSelectionEvent e) { } public void treeExpanded(TreeExpansionEvent event) { } public void treeCollapsed(TreeExpansionEvent event) { } public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { } public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { } }

ScrollPanes Los JScrollPane son componentes que permiten mostrar una vista desplazable de un

componente. Resultan muy útiles cuando el tamaño de la pantalla es limitado y se necesita mostrar bastante información.

Page 60: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

60 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

El funcionamiento del componente es sencillo, teniendo en cuenta que actúa como un contenedor más, aunque no lo es.

Cuando construyamos el objeto, debemos indicarle el componente sobre el cual debe aparece una barra de desplazamiento, y el comportamiento de las barras de desplazamiento: aparecer siempre, nunca, o cuando sea necesario. Estos valores, se corresponden con un conjunto de constantes de la interfaz ScrollPaneConstants que pueden ser:

• ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED • ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER • ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS • ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED • ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER • ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS

Lo único que debemos tener en cuenta, es que si vamos a agregar a un componente un JScrollPane, debemos agregar al contenedor principal la referencia al objeto JScrollPane.

A continuación se muestra un sencillo ejemplo

public class PanelScroll extends JFrame { public PanelScroll() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JTextArea txt = new JTextArea(); JScrollPane jsp = new JScrollPane(txt); jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); jsp.setPreferredSize(new Dimension(250, 180)); getContentPane().add(jsp); this.setSize(400, 350); this.setMinimumSize(new Dimension(300, 300)); } }

Siendo el resultado que obtenemos el siguiente:

Page 61: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

61 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

ToolTips Un tooltip es un mensaje de información que se muestra al usuario en relación a algún

componente que está activo en un contenedor. Es muy útil para ampliar información sobre lo que hace el componente como por ejemplo un botón.

Su uso es muy sencillo.

public class miToolTip extends JFrame implements ActionListener { public miToolTip() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER)); JButton btn = new JButton("Boton"); btn.setToolTipText("Si me pulsas sale un mensaje!"); getContentPane().add(btn); pack(); } public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(this, "Me has pulsado!"); } }

Lo que obtenemos es lo siguiente:

Barras de Progreso En la generación de interfaces de usuario, muchas veces es importante informar al

usuario de una forma u otra sobre algunas operaciones que pueden llevar un tiempo considerable, o directamente indicarle la situación del proceso. Esta acción se puede llevar a cabo de muchas maneras: un simple mensaje o a través de una barra de progreso, como podemos ver en un instalador, o cuando realizamos la copia de un grupo grande de ficheros de un sitio a otro de nuestro ordenador.

En Swing, se proporciona este comportamiento a través de tres clases:

- JProgressBar: es un componente gráfico al que podemos establecerle valores según una operación determinada

- ProgressMonitor: componente no gráfico que nos avisa cuando se acaba una operación

- ProgressMonitorInputStream: clase asociada a un objeto ProgressMonitor que monitoriza una operación de Entrada y Salida.

Page 62: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

62 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Veremos en este caso la implementación de JProgressBar. Tanto ProgressMonitor como ProgressMonitorInputStream se verá a posteriori en el tema de concurrencia.

JProgressBar A continuación se comentan algunos métodos que nos pueden resultar de interés para

el funcionamiento del componente:

- setValue(int i) / getValue(): establece / obtiene el valor actual de la barra - setMaximum(int i) / getMaximum(): establece / obtiene el valor máximo de la

barra de progreso - setMinimum(int i) / getMinimum(): establece / obtiene el valor mínimo de la barra

de progreso. - setString(String s) /getString(): Establece/obtiene la cadena a mostrar sobre la

barra de progreso. - setStringPainted(boolean b): establece si la barra de progreso debe mostrar su

valor actual (porcentaje) sobre ella misma. - setIndeterminate(boolean b): establece una característica a la barra de progreso

que se utiliza para indicar al usuario que el fin de la operación no se sabe exactamente. Digamos, que genera una barra como la carga del sistema Windows.

A continuación se muestra un sencillo código, con un botón y una barra de progreso que va aumentando según se pincha sobre el botón.

public class Barras extends JFrame implements ActionListener { JProgressBar jpb = null; public Barras() { jpb = new JProgressBar(SwingConstants.HORIZONTAL,0, 40); JButton btn1 = new JButton("Aumentar"); btn1.addActionListener(this); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); jpb.setStringPainted(rootPaneCheckingEnabled); jpb.setIndeterminate(true); setLayout(new FlowLayout(FlowLayout.CENTER)); getContentPane().add(jpb); getContentPane().add(btn1); setSize(450, 300); } public void actionPerformed(ActionEvent e) { if (jpb.getValue()<jpb.getMaximum()) { jpb.setValue(jpb.getValue() + 1); if (jpb.getValue() == jpb.getMaximum()) jpb.setIndeterminate(false); } } }

El resultado que obtenemos es el siguiente:

Page 63: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

63 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

Temporizadores. Timer4

Los temporizadores son unos objetos que nos permiten ejecutar un método después de un periodo de tiempo, sin necesidad que la interacción del usuario. Se basan en la ejecución de subprocesos que veremos en temas posteriores.

.

Cuando creemos el objeto temporizador, debemos indicarle el tiempo en milisegundos a partir del cual nos ejecutara un método. Este método será el implementado por la interfaz ActionListener: es decir: actionPerformed.

Los siguientes métodos pueden resultar de utilidad

- start()/stop(): inicia o para el temporizador - restart(): inicia nuevamente un temporizador parado, cancelando todas las

operaciones pendientes de ejecución - setInitialDelay(int s): tiempo en milisegundos de espera antes de iniciar la primera

ejecución del método actionPerformed. - setDelay(int s): tiempo en milisegundos que se debe esperar entre ejecuciones

sucesivas del método actionPerformed.

A continuación se muestra un sencillo ejemplo de implementación de esta clase, que intenta simular la ejecución de un reloj digital.

public class Temporizadores extends JFrame implements ActionListener { DateFormat df = new SimpleDateFormat("HH:mm:ss"); JLabel lbl = null; public Temporizadores() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER)); lbl = new JLabel(); lbl.setFont(new Font("Arial", Font.ITALIC, 28)); lbl.setText(df.format(new Date())); Timer t = new Timer(1000, this); getContentPane().add(lbl); t.setInitialDelay(3000); t.start(); pack();

4 Usar los temporizadores del paquete javax.swing

Page 64: Interfaces de Usuario Con Java (2)

Interfaces de Usuario con Java Swing

64 Javier Garrido Díaz

2º I. T. I. G. Tecnología de la Programación Universidad Europea Miguel de Cervantes

} public void actionPerformed(ActionEvent e) { lbl.setText(df.format(new Date())); } }

El resultado que se obtiene es el siguiente: