Programación Orientada a Objetos Junio, 2005
Programación con Swing Noelia Méndez Fernández Jose Luis García Valiente
Departamento de Informática y Automática Universidad de Salamanca
Jose Luis García y Noelia Méndez
RESUMEN Este documento pretende hacer una descripción de Swing, una de las APIs de Java, que se incluye en las JFC 1.1. En primer lugar se hace una introducción a Swing, describiendo el entorno en el que se encuentra, tratando por ello algunos aspectos relacionados con AWT, JFC 1.1 y JDK 1.2. Además, se realiza una breve descripción de las interfaces de usuario. Posteriormente, se describe Swing con más profundidad, analizando su arquitectura y sus componentes principales. A continuación, se hace una pequeña introducción al manejo de eventos en Swing y a los Applets. Finalmente, se analiza por qué es útil convertir una aplicación a Swing y se dan unas indicaciones para facilitar la conversión. Y por último, se explican varios ejemplos de aplicaciones con Swing.
ABSTRACT This document tries to make a description of Swing, one of the APIs of Java, which is included in JFC 1.1. First of all, this document makes an introduction to Swing, describing the IDE where it is, dealing with some aspects related to AWT, JFC 1.1 and JDK 1.2. Besides, a short description about the interfaces of user is made. Afterwards, Swing is described more deeply, analysing its architecture and main components. Later, a small introduction about the management of events in Swing and the Applets is made. Eventually, why is useful to convert an application into Swing is analysed and some indications are given to make easy the conversion. Finally,
2
some
examples
about
applications
with
Swing
are
explained.
Programación con Swing
LISTA DE CONTENIDOS -
Introducción al trabajo ................................................................................................. Pág. 6
-
Introducción a Swing .................................................................................................. Pág. 6
-
Introducción a las interfaces de usuario y el AWT ...................................................... Pág. 6
-
Swing, el AWT y las JFC............................................................................................. Pág. 7
-
La jerarquía de componentes Swing ............................................................................ Pág. 8
-
Panorámica del paquete Swing .................................................................................... Pág. 8
-
Construcción de GUI en Swing .................................................................................. Pág. 10
-
Manejo de eventos en Swing ...................................................................................... Pág. 12
-
Applets en Swing ........................................................................................................ Pág. 13
-
Conversión a Swing .................................................................................................... Pág. 13
-
Ejemplos ..................................................................................................................... Pág. 14
-
Conclusiones ............................................................................................................... Pág. 24
-
Bibliografía ................................................................................................................. Pág. 26
3
Jose Luis García y Noelia Méndez
LISTA DE FIGURAS
4
-
Figura 1: Swing, IFC, JFC y AWT .............................................................................. Pág. 7
-
Figura 2: Jerarquía de componentes Swing ................................................................. Pág. 9
-
Figura 3: Ejemplos de eventos .................................................................................... Pág. 12
-
Figura 4: Relación entre eventos y oyentes................................................................. Pág. 13
-
Figura 5: Ejemplo de ventana con pestañas ................................................................ Pág. 15
-
Figura 6: Componentes de menús............................................................................... Pág. 17
-
Figura 7: Árbol de herencia de las clases relacionadas con menús............................. Pág. 17
-
Figura 8: Detección de eventos................................................................................... Pág. 19
-
Figura 9: Menú personalizado..................................................................................... Pág. 22
-
Figura 10: Otra distribución de un menú .................................................................... Pág. 22
Programación con Swing
LISTA DE TABLAS -
Tabla 1: Crear y configurar un TabbedPane ............................................................... Pág. 15
-
Tabla 2: Insertar, Eliminar, Encontrar y Seleccionar Pestañas ................................... Pág. 16
-
Tabla 3: Cambiar la Apariencia de las Pestañas ......................................................... Pág. 16
-
Tabla 4: Crear y configurar barras de menús .............................................................. Pág. 22
-
Tabla 5: Crear y Rellenar Menús ................................................................................ Pág. 22
-
Tabla 6: Crear y Rellenar Menús Desplegables.......................................................... Pág. 23
-
Tabla 7: Implementar Ítems de Menú ......................................................................... Pág. 23
5
Jose Luis García y Noelia Méndez
1.
INTRODUCCIÓN AL TRABAJO
Este trabajo pretende ser una pequeña introducción a Swing, con la que se intenta mostrar al lector una visión general sobre el mundo de las interfaces gráficas de usuario, y más concretamente, sobre el desarrollo de éstas con Java y sus APIs. Puesto que tan sólo se trata de una breve introducción al tema, lo que se pretende es captar la atención del lector y mostrar las ventajas que ofrece éste tipo de programación. En primer lugar, se realiza una introducción a Swing, el AWT y las interfaces de usuario, tratando de ésta forma de centrar al lector en el tema a tratar. Una vez realizada dicha introducción, se describirá brevemente el paquete Swing, para dar una idea de la jerarquía de componentes que se puede utilizar con Swing y de sus utilidades. También se mencionará el manejo de eventos en Swing, así como los Applets, aunque de una forma muy superficial, ya que debido a la gran amplitud de variaciones que pueden darse, sería muy extenso hacer una descripción detallada. A continuación, se exponen los motivos por los que resulta interesante convertir las aplicaciones a Swing. Para terminar, se examinarán más concretamente dos de las clases que ofrece Swing: la clase Tabbed Pane y la clase Menu. Para aquellas personas que después de leer este documento se sientan atraídas por la construcción de interfaces gráficas de usuario con Swing, al final del documento se incluyen las referencias, para facilitar la búsqueda de información a todo el que desee profundizar en el tema.
2.
INTRODUCCIÓN A SWING
Swing es una de las mejoras principales que ha experimentado el JDK en su versión 1.2 con respecto a la versión 1.1, y representa la nueva generación de AWT. También es una de las API de las Clases de Fundamentos de Java (JFC), lo cual es el resultado de un esfuerzo de colaboración muy grande entre Sun, Netscape, IBM y otras empresas. Lo que da a Swing su importancia es el poder que ofrece para desarrollar interfaces gráficas de usuario (GUI) para applets y aplicaciones. La cantidad y calidad de los controles GUI que ofrece Swing no tiene rival en ningún otro juego de herramientas GUI. El origen de los controles GUI que presenta Swing lo encontramos en las Clases de Fundamentos de Internet de Netscape (IFC). Los componentes Swing van más allá de las IFC, hasta el punto de que no hay un parecido apreciable entre los componentes Swing y los de las IFC. Swing ofrece también la posibilidad de cambiar fácil y rápidamente el aspecto y sensación (L&F) de un único componente o grupo de componente. Esta posibilidad, que se conoce como aspecto y sensación conectables (PL&F), es un sello distintivo de Swing.
3.
INTRODUCCIÓN A LAS INTERFACES DE USUARIO Y EL AWT
Para poder apreciar la importancia de Swing, haremos primero una introducción a las interfaces de usuario y al AWT. El interfaz de usuario es la parte del programa que permite a éste interactuar con el usuario. Las interfaces de usuario pueden adoptar muchas formas, que van desde la simple línea de comandos hasta las interfaces gráficas que proporcionan las aplicaciones más modernas. El interfaz de usuario es el aspecto más importante de cualquier aplicación. Una aplicación sin un interfaz fácil, impide que los usuarios saquen el máximo rendimiento del programa. Java proporciona los elementos básicos para construir interfaces de usuario a través del AWT, y opciones para mejorarlas mediante Swing, que sí permite la creación de interfaces de usuario de gran impacto y sin demasiados quebraderos de cabeza por parte del programador. 6
Programación con Swing
Al nivel más bajo, el sistema operativo transmite información desde el ratón y el teclado como dispositivos de entrada al programa. El AWT fue diseñado pensando en que el programador no tuviese que preocuparse de detalles como controlar el movimiento del ratón o leer el teclado, ni tampoco atender a detalles como la escritura en pantalla. El AWT constituye una librería de clases orientada a objeto para cubrir estos recursos y servicios de bajo nivel. Debido a que el lenguaje de programación Java es independiente de la plataforma en que se ejecuten sus aplicaciones, el AWT también es independiente de la plataforma en que se ejecute. El AWT proporciona un conjunto de herramientas para la construcción de interfaces gráficas que tienen una apariencia y se comportan de forma semejante en todas las plataformas en que se ejecute. Los elementos de interfaz proporcionados por el AWT están implementados utilizando toolkits nativos de las plataformas, preservando una apariencia semejante a todas las aplicaciones que se creen para esa plataforma. Este es un punto fuerte del AWT, pero también tiene la desventaja de que un interfaz gráfico diseñado para una plataforma, puede no visualizarse correctamente en otra diferente. Estas carencias del AWT son subsanadas en parte por Swing, y en general por las JFC.
4.
SWING, EL AWT Y LAS JFC JFC AWT IFC
Swing
Figura 1 Swing, IFC, JFC y AWT
La Figura 1 muestra la relación existente entre Swing, el AWT y las JFC. Las JFC subsumen y amplían el AWT original, y constan de las siguientes API principales: -
AWT.
-
Swing.
-
Java 2D.
-
Drag-and-Drop.
-
Accessibility.
Aunque Swing esté separado del AWT, se implementa en términos de clases AWT básicas. El AWT proporciona la interfaz entre el sistema de ventanas nativo subyacente y los componentes GUI de Java. Swing utiliza esta interfaz, pero no se apoya en componentes del AWT para hacer uso de objetos nativos. En lugar de ello, los componentes Swing están escritos en Java puro. Esto ofrece ventajas significativas. Permite a los componentes Swing ser independientes del sistema de ventanas nativo, lo cual implica que pueden ejecutarse en cualquier sistema de ventanas que admita el AWT. También permite a los componentes Swing ser independientes de cualquier limitación de los sistemas de ventanas nativos. Esta independencia permite a Swing controlar y adaptar su aspecto y sensación (de ahí la aparición de PL&F). Entre los componentes nuevos que incluye Swing hay desde paneles tabulados y bordes estilizados hasta barras deslizadoras y efectos giratorios. Estos componentes nuevos, en sí mismos, hacen que Swing constituya un agregado de primera magnitud a la API Java. La galería de componentes Swing, que se encuentra en http://java.sun.com/products/jfc/swingdoc-
7
Jose Luis García y Noelia Méndez
current/comp_gal.html, muestra algunos de ellos. Swing también incorpora un programa de demostración llamado SwingSet. Swing también ofrece una implementación de Java puro de muchos de los componentes tradicionales del AWT. Estos componentes tienen la misma funcionalidad que los componentes del AWT y todas las ventajas de Swing. Swing es compatible con el AWT, y los componentes Swing se pueden utilizar con los componentes del AWT. Sin embargo, los compenentes Swing sólo se pueden usar con el modelo de eventos del JDK 1.1. No admiten el modelo de eventos del JDK 1.0. La arquitectura PL&F de Swing facilita la personalización de tanto del aspecto como del comportamiento de cualquier control Swing o de cualquier grupo de estos controles. Swing también incorpora varios L&F predefinidos, entre los que reincluye el Metal L&F predeterminado, el Motif L&F y el Windows L&F. Los L&F para Macintosh y otras plataformas también se están desarrollando.
5.
LA JERARQUÍA DE COMPONENTES SWING
Swing consta de nueve paquetes y cientos de clases e interfaces. No obstante, la clase JComponent de java.awt.swing es la clase superior de la jerarquía de componentes Swing. La clase JComponent es una subclase de la clase java.awt.container y, por tanto, es a la vez un componente y un contenedor en el sentido del AWT. Dado que JComponent es la superclase de todos los componentes Swing, todos ellos descienden de java.awt.Container y java.awt.Component. La Figura 2 muestra la jerarquía de componentes Swing. La primera cosa que se debe tener en cuenta es que todos los componentes empiezan por la letra J, seguida por el tipo de componente que admite la clase. Jcomponent consta de las subclases directas que se muestran en la Figura 2.
6.
PANORÁMICA DEL PAQUETE SWING
Swing es una API grande que consta de nueve paquetes y de numerosas clases e interfaces. La mayor parte de componentes Swing se incluyen en el paquete java.awt.swing, el cual ofrece asimismo clases e interfaces que admiten y manejan los componentes GUI. El paquete java.awt.swing.border ofrece una serie de interesantes bordes que se pueden usar con los componentes Swing. Estos bordes le ayudan a adaptar el aspecto y sensación de los conjuntos de componentes. El paquete java.awt.swing.event define los eventos y auditores de eventos que utilizan los componentes Swing. Es sin duda una buena idea examinar la lista de eventos y de auditores de eventos para tener una idea de las interacciones de usuario que admite Swing. El paquete java.awt.swing.table ofrece clases e interfaces que admiten el objeto JTable enriquecido y flexible. Estas clases e interfaces se usan para adaptar las características de muestra de una tabla. Los paquetes java.awt.swing.text ofrecen varias clases e interfaces que admiten componentes de texto. Estas clases e interfaces controlan el signo de intercalación, resaltado, formato y demás aspectos del texto que se introduce y se modifica en los componentes del texto. El paquete java.awt.swing.text.html contiene la clase única HTMLEditorKit. Esta clase admite la implementación de un editor HTML sencillo pero potente. El paquete java.awt.swing.text.rtf es parecido al paquete java.awt.swing.text.html. Contiene la clase única RTFEditorKit, la cual ofrece la posibilidad de modificar Texto con Formato Enriquecido (RTF).
8
Programación con Swing
El paquete java.awt.swing.tree ofrece clases e interfaces que admiten el uso del componente JTree. El paquete java.awt.swing.undo admite operaciones hacer y rehacer.
JComponent • AbstractButton • JButton • JMenuItem • JCheckBoxMenuItem • JMenu • JRadioButtonMenuItem • JToggleButton • JCheckBox • JRadioButton • JComboBox • JInternalFrame • JLabel • DefaultTableCellRenderer(java.awt.swing.table) • JLayeredPane • JDesktopPane • JList • JMenuBar • JOptionPane • JPanel • ColorChooserPanel • JPopupMenu • JProgressBar • JRootPane • JScrollBar • JScrollPane • JSeparator • JSlider • JSplitPane • JTabbedPane • JTable • JTableHeader(java.awt.swingn.table) • JTextComponent(java.awt.swing.text) • JEditorPane JTextPane • • JTextArea • JTextField • JPasswordField • JToolBar • JToolTip • JTree • JViewport
Figura 2. La jerarquía de componentes Swing
9
Jose Luis García y Noelia Méndez
7.
CONSTRUCCIÓN DE GUI EN SWING
La construcción de una GUI en Swing es muy similar a la construcción de GUI en el AWT, exceptuando que la primera tendrá muchas más clases de componentes con las que trabajar. A continuación se describen las clases que se usan para la construcción de GUI y se señalan las mejoras que Swing proporciona, comparando éstas clases con las de AWT. - Ventanas Swing, al igual que AWT, proporciona una jerarquía de clases Window. Las clases de la ventana de Swing constituyen extensiones de la jerarquía de clases Window del AWT. La clase JWindow amplía la clase Window. La clase JFrame amplía la clase JFrame del AWT y la clase JDialog amplía la clase Dialog del AWT. Las clases JWindow, JFrame y JDialog difieren de sus homólogos del AWT en que utilizan un panel de contenido separado para agregar y diseñar componentes GUI. Este panel es un objeto Container al que se accede a través del método getContentPane(). El panel de contenido es una parte de un objeto JRootPane que contiene otros paneles que se usan para sobreponerse a componentes e interceptar eventos del ratón y del teclado. - Menús Los menús de Swing, al igual que las ventanas de Swing, son análogos a sus homólogos del AWT. Las clases JMenuBar, JMenu, JMenuItem, JCheckBoxMenuItem y JRadioButtonMenuItem se utilizan de la misma forma que las clases MenuBar, Menu, MenuItem y CheckboxMenuItem del AWT, sólo que con una diferencia fundamental. Las clases de menús de Swing son todas ellas subclases de la clase JComponent y, por tanto, de la clase Component. Esto implica que los menús de Swing, al contrario que sus homólogos del AWT, constituyen componentes de primera clase y se pueden usar con cualquiera de las clases Container. La clase JPopupMenu es equivalente a la clase PopupMenu del AWT. Otra atractiva característica de los menús de Swing es la posibilidad de utilizar imágenes de iconos en los menús. Se puede añadir una imagen a un elemento de menú por medio de su constructor. - Paneles La clase JPanel es el equivalente de Swing a la clase Panel del AWT. Esta clase, al igual que sucede en otras clases de JComponent, ofrece la posibilidad de agregar un borde. - Diseños Los contenedores de Swing admiten todos los diseños posibles del AWT, entre los que se incluye el diseño null, además de admitir otros diseños nuevos. - Iconos Una de las características más útiles que Swing ofrece es la posibilidad de agregar iconos a los componentes, como etiquetas, botones, elementos de menú, etc. La interfaz Icon define los métodos que las clases de iconos deben implementar. La clase ImageIcon proporciona una implementación predeterminada de esta interfaz. Los objetos ImageIcon se pueden construir a partir de archivos de imagen, URL que apuntan a archivos de imagen u objetos Image del AWT. - Bordes El paquete java.awt.swing.border proporciona la interfaz Border, la cual define los métodos que necesitan ser implementados por todas las clases de bordes. La clase
10
Programación con Swing
AbstractBorder implementa la interfaz Border y es la superclase de las clases de bordes de Swing. - Información sobre herramientas La clase JToolTip ofrece la posibilidad de agregar cuadros de texto emergentes que aparecen cuando se posa el ratón sobre un componente. Estos componentes, que admiten información sobre herramientas, permiten que éstas vengan especificadas en sus respectivos constructores. El método setToolTipText() de la clase JComponent se puede usar también para especificar la información sobre herramientas de un componente. - Barras de herramientas La clase JToolBar ofrece la posibilidad de utilizar barras de herramientas movibles y acoplables con Swing. Los objetos de esta clase son contenedores de otros componentes Swing o del AWT. Los objetos JToolBar típicos contienen objetos JButton que se construyen por medio de iconos de imagen. - Etiquetas y botones Las clases JLabel y JButton proporcionan los equivalentes de Swing a las clases Label y Button del AWT. La implementación de Swing ofrece la ventaja de poder usar iconos a la vez que texto. Los constructores JLabel() y JButton() permiten que se especifique un icono. Además, ambas clases admiten el método setIcon() para establecer un icono una vez que se ha construido el objeto. - Componentes de texto Las clases JTextComponent, JTextField y JTextArea son los equivalentes de Swing de las clases TextCompoenent, TextField y TextArea del AWT. Además, Swing proporciona la clase TextPane para trabajar con documentos de texto, que se pueden marcar con estilos de texto diferentes. - Listas y cuadros combinados Las clases JComboBox y JList ofrecen la posibilidad de presentarle al usuario una lista de selecciones gráficas de texto. La clase JComboBox implementa una lista desplegable, parecida a una lista de opciones Motif. La clase JList es una lista de selecciones individuales o múltiples en las que se pueden ver muchos elementos. - Deslizadores y barras de progreso Las clases JSlider y JProgressBar carecen de equivalentes en el AWT. Ambas clases admiten orientaciones horizontales y verticales. La clase JProgressBar se utiliza típicamente para mostrar el progreso de una tarea, como la carga de una imagen. La clase JSlider se usa para ajustar o controlar el valor de una variable dentro del intervalo admisible. - Barras de desplazamiento El JScrollPane simplifica en gran medida el uso de las barras de desplazamiento. El método getViewport() devuelve un objeto JViewport en el que se pueden ir añadiendo componentes. En la mayoría de los casos, sólo necesita agregar componentes al objeto JViewport para que uno se pueda desplazar automáticamente por ellos. - Tablas La clase JTable es otro componente de Swing que carece de equivalente en AWT. JTable ofrece una posibilidad muy flexible para crear y mostrar tablas. Permite construir tablas a partir de arrays o vectores de objetos, o bien a partir de objetos que implementan la interfaz TableModel.
11
Jose Luis García y Noelia Méndez
La interfaz JTableModel define métodos para los objetos que especifican el contenido de una tabla. La clase AbstractTableModel ofrece una implementación predeterminada de la interfaz JTableModel. Esta clase se amplía típicamente para proporcionar una implementación personalizada de modelo de tabla. La clase JTable ofrece la posibilidad de editar tablas. El método setCellEditor() permite que un objeto de la interfaz TableCellEditor sea identificado como el editor de celdas de una tabla. - Árboles Una de las clases nuevas más interesantes que ofrece Swing es la clase JTree. Esta clase implementa una estructura en forma de árbol que se puede usar para mostrar datos jerárquicos. La interfaz TreeNode define métodos que tienen que implementar los nodos de un objeto JTree. La clase DefaulMutableTreeNode proporciona una implementación predeterminada de la interfaz TreeNode. Los árboles se crean construyendo objetos de la interfaz TreeNode para luego añadirlos todos juntos (a través del método add()). Cuando todos los objetos TreeNode se hayan juntado, el objeto TreeNode resultante se pasa al constructor JTree. La presentación predeterminada de un objeto JTree utiliza un icono de carpeta con el fin de identificar los nodos de árbol que tienen nodos inferiores y un icono de archivo para identificar las ramificaciones del árbol. El método setCellRenderer() de la clase JTree se usa para identificar una prestación de árbol alternativa.
8.
MANEJO DE EVENTOS EN SWING
Cada vez que el usuario teclea un carácter o pulsa un botón del ratón, ocurre un evento. Cualquier componente puede ser notificado del evento. Todo lo que tiene que hacer es implementar el interface apropiado y ser registrado como un oyente de evento del evento fuente apropiado. Los componentes Swing pueden generar muchas clases de evento. El paquete java.awt.swing.event define una serie de interfaces auditoras de eventos y clases de eventos que se usan con los componentes Swing. Además, muchos de los componentes Swing también utilizan eventos del AWT. En la figura 3 mostramos unos pocos ejemplos:
Figura 3 Ejemplos de eventos
Cada evento está representado por un objeto que ofrece información sobre el evento e identifica la fuente. Las fuentes de los eventos normalmente son componentes, pero otros tipos de objetos también pueden ser fuente de eventos. Como muestra la siguiente figura, cada fuente
12
Programación con Swing
de evento puede tener varios oyentes registrados. Inversamente, un sólo oyente puede registrarse con varias fuentes de eventos.
Figura 4 Relación entre eventos y oyentes
9.
APPLETS DE SWING
La clase JApplet es el equivalente de Swing de la clase Applet. JApllet se parece a JFrame en que admite un panel de contenido separado. A este contenedor se accede a través del método getContentPane(). La barra de menús debe ser un objeto de la clase JMenuBar.
10.
CONVERSIÓN A SWING
9.1 ¿Por qué convertir a Swing? Ante la pregunta, ¿por qué debo convertir a Swing?, la razón más fuerte es que Swing ofrece muchos beneficios a los programadores y usuarios finales. Entre ellos: -
El rico conjunto de componentes listo-para-usar significa que podemos añadir características divertidas a nuestros programas -- botones con imágenes, barras de herramientas, paneles con pestañas, display HTML, imágenes en ítems de menú, un selector de color, etc.
-
También significa que podríamos reemplazar algunos componentes personalizados con componentes Swing más extensibles y eficaces.
-
Tener modelos separados de datos y estados hace que los componentes Swing sean altamente personalizables y permite compartir datos entres componentes.
-
La arquitectura conectable del aspecto y comportamiento swing ofrece una amplia selección de aspectos y comportamientos. Junto al aspecto y comportamiento de la plataforma usual, podemos usar el aspecto y comportamiento Java e incluso aspectos y comportamientos de terceras partes.
-
Los componentes Swing tienen soporte interno para accesibilidad, lo que hace que nuestros programas pueden usarse automáticamente con tecnologías asistivas.
-
Los componentes Swing continuarán ampliándose en el futuro.
-
Por lo que la pregunta sería ahora "¿Por qué no debo convertir a Swing?" Es razonable posponer la conversión si pensamos que nuestros usuarios no podrán ejecutar los programas Swing de forma conveniente. Por ejemplo, su nuestro programa es un applet y queremos que todo el mundo pueda usarlo en internet, deberíamos considerar cuantos navegantes del Web tienen navegadores que puedan ejecutar programas Swing. En el momento de escribir esto, la mayoría de los navegadores no tienen soporte Swing interno; los usuarios deben añadirlo descargando e instalando Java Plug-in.
9.2 ¿Cómo convertir a Swing?
13
Jose Luis García y Noelia Méndez
Dado que Swing ofrece componentes GUI que son equivalentes a los componentes del AWT, resulta fácil convertir las aplicaciones y applets a Swing. Las aplicaciones se convierten a Swing reemplazando la clase Frame por la clase JFrame y utilizando getContentPane() para acceder al contenedor del marco. Los componentes GUI que se hubieran añadido al Frame se añaden al contenedor del marco. Los applets se convierten deforma parecida con la clase JApplet reemplazando a la clase Applet. La mayor parte de los componentes GUI del AWT pueden convertirse a Swing anteponiendo al nombre de la clase de AWT la letra ‘J’.
11.
EJEMPLOS
Puesto que Swing tiene una gran cantidad de componentes y sería demasiado extenso detallar cada uno de éstos, a continuación se analizan de forma detallada sólo dos de ellos. Para conocer el funcionamiento del resto de los componentes, en la bibliografía se muestran algunas referencias para encontrar la información necesaria.
10.1 Cómo utilizar la Clase Tabbed Pane 10.1.1
¿Qué es la clase Tabbed Pane?
Con la clase JTabbedPane, podemos tener varios componentes (normalmente objetos JPanel) compartiendo el mismo espacio. El usuario puede elegir qué componente ver seleccionando la pestaña del componente deseado. 10.1.2
Construir una aplicación con un Tabbed Pane
Para crear un TabbedPane, simplemente se ejemplariza un JTabbedPane, se crean los componentes que deseemos mostrar, y luego los añadimos al TabbedPane utilizando el método addTab. Compilando y ejecutando el siguiente código, se obtiene como resultado la ventana que aparece representada en la Figura 5. ImageIcon icon = new ImageIcon("images/middle.gif"); JTabbedPane tabbedPane = new JTabbedPane(); Component panel1 = makeTextPanel("Blah"); tabbedPane.addTab("One", icon, panel1, "Does nothing"); tabbedPane.setSelectedIndex(0); Component panel2 = makeTextPanel("Blah blah"); tabbedPane.addTab("Two", icon, panel2, "Does twice as much nothing"); Component panel3 = makeTextPanel("Blah blah blah"); tabbedPane.addTab("Three", icon, panel3, "Still does nothing"); Component panel4 = makeTextPanel("Blah blah blah blah"); tabbedPane.addTab("Four", icon, panel4, "Does nothing at all");
14
Programación con Swing
Figura 5 Ejemplo de ventana con pestañas
Esta imagen representa una aplicación que utiliza cuatro TabbedPane. Como podemos apreciar, la ventana está constituida por cuatro pestañas. Una pestaña puede tener un tooltip, y puede mostrar tanto texto como una imagen. El ejemplo muestra las pestañas en sus posiciones por defecto, en la parte superior del TabbedPane. Podemos cambiar las posiciones de las pestañas a la izquierda, derecha, o abajo. Poniendo el cursor sobre una pestaña, después de un corto tiempo, se verá una ayuda (tooltip) asociada con la pestaña. Como conveniencia se debe añadir el texto de la ayuda (tooltip) cuando se añade el componente al TabbedPane. 10.1.3
El API TabbedPane
Las siguientes tablas listan los métodos y constructores más utilizados de TabbedPane. El API para utilizar TabbedPane se divide en estas categorías: -
Crear y configurar un TabbedPane.
-
Insertar, Eliminar, Encontrar y Seleccionar Pestañas.
-
Cambiar la apariencia de las pestañas.
Tabla 1 Crear y configurar un TabbedPane
Método JTabbedPane() JTabbedPane(int)
Propósito Crea un TabbedPane. El argumento opcional indica dónde deberían aparecer las pestañas. Por defecto, las pestañas aparecen en la parte superior. Se pueden especificar estas posiciones (definidas en el interface SwingConstants, que implementa TabbedPane): TOP, BOTTOM, LEFT, LEFT.
addTab(String, Icon, Component, String) addTab(String, Icon, Component) addTab(String, Component)
Añade una nueva pestaña al TabbedPane. El primer argumento especifica el texto de la pestaña. El argumento Icon es opcional e indica el icono de la pestaña. El argumento Component especifica el componente que el TabbedPane debería mostrar cuando se selecciona la pestaña. El cuarto argumento, si existe, especifica el texto del tooltip para la pestaña.
15
Jose Luis García y Noelia Méndez
Tabla 2 Insertar, Eliminar, Encontrar y Seleccionar Pestañas
Método
Propósito
insertTab(String, Icon, Component, String, int)
Inserta una pestaña en el índice especificado, donde la primera pestaña tiene índice 0. Los argumentos son los mismos que para addTab.
remove(Component) removeTabAt(int)
Elimina la pestaña correspondiente al índice o componente especificado.
removeAll()
Elimina todas las pestañas.
int indexOfComponent(Component)
Devuelve el índice de la pestaña que tiene el componente, título o icono especificados.
int indexOfTab(String) int indexOfTab(Icon) void setSelectedIndex(int) void setSelectedComponent(Component)
int getSelectedIndex() Component getSelectedComponent()
Selecciona la pestaña que tiene el índice o componente especificado. Seleccionar una pestaña tiene el efecto de mostrar su componente asociado. Devuelve el índice o componente de la pestaña seleccionada.
Tabla 3 Cambiar la Apariencia de las Pestañas
Método
Propósito
void setComponentAt(int, Component)
Selecciona u obtiene qué componente está asociado con la pestaña del índice especificado. La primera pestaña tiene índice 0.
Component getComponentA(int) void setTitleAt(int, String) String getTitleAt(int) void setIconAt(int, Icon) Icon getIconAt(int)
Selecciona u obtiene el título de la pestaña del índice especificado. Selecciona u obtiene iconos pestaña del índice especificado.
mostrados
void setDisabledIconAt(int, Icon) Icon getDisabledIconAt(int) void setBackgroundAt(int, Color) Color getBackgroundAt(int) void setForegroundAt(int, Color) Color getForegroundAt(int)
16
Selecciona u obtiene el color de fondo o de primer plano usado por la pestaña del índice especificado. Por defecto, una pestaña utiliza los colores del TabbedPane. Por ejemplo, si el color de primer plano del TabbedPane es negro, entonces todos los títulos de las pestañas serán en negro, excepto para aquellas en que especifiquemos otro color usando setForegroundAt.
Programación con Swing
void setEnabledAt(int, boolean) boolean isEnabledAt(int)
Selecciona u obtiene el estado activado de la pestaña del índice especificado.
10.2 Cómo Utilizar Menús 10.2.1
Qué es un Menú
Un menú proporciona una forma de ahorrar espacio y permitir al usuario elegir una entre varias opciones. Otros componentes con los que el usuario puede hacer una elección incluyen combo boxes, lists, radio buttons, y tool bars. Los menús son únicos en que, por convención, no se sitúan con los otros componentes en el UI. En su lugar, aparecen en una barra de menú o en un menú desplegable. Una barra de menú contiene uno o más menús, y tiene una posición dependiente de la plataforma, normalmente debajo de la parte superior de la ventana. Un menú desplegable es un menú que es invisible hasta que el usuario hace una acción del ratón específica de la plataforma, como pulsar el botón derecho del ratón sobre un componente. Entonces el menú desplegable aparece bajo el cursor. La figura 6 muestra los componentes Swing que implementan cada parte de un sistema de menús.
Figura 6 Componentes de un menú
10.2.2
La herencia de componentes de menú
Figura 7 Árbol de herencia de las clases relacionadas con menús.
17
Jose Luis García y Noelia Méndez
Como se ve en la figura 7, los ítems de menús (incluidos los propios menús) son simples botones. Un menú, a pesar de ser un botón, muestra sus ítems ya que cuando se activa, automáticamente trae un menú desplegable que muestra sus ítems. 10.2.3
Construir una aplicación con un Menú
A continuación tenemos el fragmento de código que crea los menús mostrados en la figura 4. Como este código no tiene manejo de eventos, los menús no hacen nada útil, excepto verse como serían. Si se ejecuta el ejemplo, observaremos que a pesar de no tener un manejo de eventos, los menús y submenús aparecen cuando deben, y los checkbox y los botones de radio responden apropiadamente cuando el usuario los elige. menu.add(cbMenuItem); cbMenuItem = new JCheckBoxMenuItem("Another one"); menu.add(cbMenuItem); //a submenu menu.addSeparator(); submenu = new JMenu("A submenu"); menuItem = new JMenuItem("An item in the submenu"); submenu.add(menuItem); menuItem = new JMenuItem("Another item"); submenu.add(menuItem); menu.add(submenu); //Build second menu in the menu bar. menu = new JMenu("Another Menu"); menuBar.add(menu);
Como se ve en el código, para configurar una barra de menú para un JFrame, se utiliza el método setJMenuBar. Para añadir un JMenu a un JMenuBar, se utiliza el método add(JMenu). Para añadir ítems de menú y submenús a un JMenu, se utiliza el método add(JMenuItem). Estos métodos y otros más se listan en El API de JMenu. 10.2.4
Manejar Eventos desde Ítems de Menús
Para detectar cuando el usuario selecciona un JMenuItem, se puede escuchar por eventos action (igual que se haría para un JButton). Para detectar cuando el usuario selecciona un JRadioButtonMenuItem, se puede escuchar tanto por eventos action, como por eventos item. Para JCheckBoxMenuItems, generalmente se escuchan eventos de item. La figura 8 muestra un programa que añade detección de eventos al ejemplo anterior.
18
Programación con Swing
Figura 8 Detección de eventos
A continuación se muestra un fragmento de código que implementa el manejo de eventos:
public class MenuDemo ... implements ActionListener, ItemListener { ... public MenuDemo() { ...//for each JMenuItem instance: menuItem.addActionListener(this); ...//for each JRadioButtonMenuItem: rbMenuItem.addActionListener(this); ...//for each JCheckBoxMenuItem: cbMenuItem.addItemListener(this); ... } public void actionPerformed(ActionEvent e) { ...//Get information from the action event... ...//Display it in the text area... } public void itemStateChanged(ItemEvent e) { ...//Get information from the item event... ...//Display it in the text area... }
Para traer un menú desplegable (JPopupMenu), debemos registrar un oyente de ratón para cada componente al que debería estar asociado el menú desplegable. El oyente de mouse debe detectar las peticiones del usuario para que aparezca el menú desplegable.
19
Jose Luis García y Noelia Méndez
Para las plataformas Windows y Motif, el usuario trae un menú desplegable pulsando el botón derecho del ratón mientras el cursor está sobre el componente adecuado. El oyente de mouse trae un menú desplegable llamando a setVisible(true) sobre el ejemplar apropiado de JPopupMenu. El siguiente fragmento de código, muestra cómo crear y mostrar menús desplegables: ...//where instance variables are declared: JPopupMenu popup; ...//where the GUI is constructed: //Create the popup menu. popup = new JPopupMenu(); menuItem = new JMenuItem("A popup menu item"); menuItem.addActionListener(this); popup.add(menuItem); menuItem = new JMenuItem("Another popup menu item"); menuItem.addActionListener(this); popup.add(menuItem); //Add listener to components that can bring up popup menus. MouseListener popupListener = new PopupListener(); output.addMouseListener(popupListener); menuBar.addMouseListener(popupListener); ... class PopupListener extends MouseAdapter { public void mousePressed(MouseEvent e) { maybeShowPopup(e); } public void mouseReleased(MouseEvent e) { maybeShowPopup(e); } private void maybeShowPopup(MouseEvent e) { if (e.isPopupTrigger()) { popup.show(e.getComponent(), e.getX(), e.getY()); } } }
20
Programación con Swing
Los menús desplegables tienen unos pocos detalles interesantes de implementación. Uno es que cada menú tiene un menú desplegable apropiado. Cuando el menú se activa, utiliza su menú desplegable para mostrar sus ítems de menú. Otro detalle es que un propio menú desplegable utiliza otro componente para implementar la ventana que contiene los ítems del menú. Dependiendo de las circunstancias bajo las que se muestre el menú desplegable, podría implementar su "ventana" utilizando un componente de peso ligero (como un JPanel), un componente de peso medio (como un Panel), o una ventana de peso pesado (Window). Las ventanas desplegables de peso ligero son más eficientes que las ventanas de peso pesado, pero no funcionan bien si tenemos componentes pesados dentro de nuestro GUI. Específicamente, cuando un área de una ventana desplegable de peso ligero se intersecciona con un componente de peso pesado, el componente de peso pesado se dibuja encima. Esta es una de las razones por la que se recomienda no mezclar componentes de peso ligero y de peso pesado. Si realmente se necesita utilizar un componente de peso pesado en el GUI, se puede utilizar el método setLightWeightPopupEnabled de JPopupMenu para desactivar las ventanas desplegables de peso ligero. 10.2.5
Personalizar la Distribución de un Menú
Como los menús se hacen con componentes ordinarios Swing, se pueden personalizar fácilmente. Por ejemplo, se puede añadir cualquier componente de peso ligero a un JMenu o JMenuBar. Y como JMenuBar utiliza BoxLayout, se puede personalizar la distribución de la barra de menú añadiéndole componentes invisibles. Aquí mostramos un ejemplo que añade un componente glue a una barra de menú, para que el último elemento del menú se sitúe en el lado derecho de la barra de menú: ...//create and add some menus... menuBar.add(Box.createHorizontalGlue()); ...//create the LEFTmost menu... menuBar.add(LEFTMenu); En la figura 9 podemos ver una imagen del resultado.
Figura 9 Menú personalizado
Otra forma de cambiar el aspecto de un menú es cambiar el controlador de distribución que lo controla. Por ejemplo, se puede cambiar el controlador de distribución de la barra de menú del valor por defecto BoxLayout de izquierda-derecha, a algo como un GridLayout. También podemos cambiar como un menú activado u otro menú desplegable distribuye sus ítems. En la figura 10 se muestra una imagen de una aplicación en la que se ha modificado la distribución del menú.
Figura 10 Otra distribución de un menú
21
Jose Luis García y Noelia Méndez
10.2.6
El API de JMenu
Las siguientes tablas listan los métodos y constructores más utilizados de Jmenu. El API se divide en estas categorías: -
Crear y Configurar Barras de Menú.
-
Crear y Rellenar Menús.
-
Crear, Rellenar y Controlar Menús Desplegables.
-
Implementar Ítems de Menú.
Tabla 4 Crear y configurar barras de menús
Método
Propósito
JMenuBar()
Crea una barra de menú.
void setJMenuBar(JMenuBar)
Selecciona u obtiene la barra de menú de un applet, dialog, frame, o root pane.
JMenuBar getJMenuBar() (en JApplet, JRootPane)
JDialog,
JFrame,
void setMenuBar(JMenuBar) JMenuBar getMenuBar() (en JInternalFrame)
En las siguientes versiones de Swing y del JDK 1.2, los frames internos también soportarán estos métodos. Selecciona u obtiene la barra de menú de un Frame interno. En las siguientes versiones de Swing y del JDK 1.2, este método será anulado y deberíamos utilizar setJMenuBar/getJMenuBar.
Tabla 5 Crear y Rellenar Menús
Método
Propósito
JMenu()
Crea un menú.
JMenuItem add(JMenuItem)
Añade un ítem de menú al final del menú.
JMenuItem add(Action) void add(String)
Si el argumento es un string, el menú crea automáticamente un objeto JMenuItem que muestra el texto especificado.
void addSeparator()
Añade un separador la final del menú.
>JMenuItem insert(JMenuItem, int)
Inserta un ítem de menú o un separador en un menú, en la posición especificada. El primer ítem de menú es la posición 0, el segundo la posición 1, etc. Los argumentos JMenuItem, Action, y String se tratan de la misma forma que en los correspondientes métodos add.
JMenuItem insert(Action, int) void insert(String, int) void insertSeparator(int)
void remove(JMenuItem) void remove(int) void removeAll()
22
Elimina el ítem o ítems especificados del menú. Si el argumento es un entero, especifica la posición del ítem a eliminar.
Programación con Swing
Tabla 6 Crear y Rellenar Menús Desplegables
Método JPopupMenu() JPopupMenu(String)
JMenuItem add(JMenuItem) JMenuItem add(Action)
Propósito Crea un menú desplegable. El argumento string opcional especifica el título que el aspecto y comportamiento podría mostrar como parte de la ventana desplegable. Añade un ítem de menú al final del menú desplegable.
void addSeparator()
Añade un separador al final del menú desplegable.
void insert(Component, int)
Inserta un ítem de menú en la posición especificada. El primer ítem del menú está en la posición 0, el segundo en la posición 1, etc. El argumento Component específica el ítem de menú a añadir. El argumento Action es tratado de la misma forma que en el método add correspondiente.
JMenuItem insert(Action, int)
void remove(JMenuItem) void remove(int) void removeAll()
static void setDefaultLightWeightPopupEnabled (boolean)
Elimina el ítem o ítems especificados del menú. Si el argumento es un entero, especifica la posición del elemento del menú a eliminar. Por defecto, Swing implementa una ventana de menú utilizando un componente de peso ligero. Esto causa problemas su utilizamos componentes de peso pesado en nuestro programa Swing. Para evitar estos problemas, se puede llamar a JPopupMenu.setDefaultLightWei ghtPopupEnabled(false).
void show(Component, int, int)
Muestra el menú desplegable en la posición X,Y (especificada en el orden de los argumentos enteros) en el sistema de coordenadas del componente especificado.
Tabla 7 Implementar Ítems de Menú
Método
Propósito
JMenuItem()
Crea un ítem de menú normal. El argumento icon, si existe, especifica el icono que debería mostrar el ítem de menú. Igualmente el argumento String, especifica el texto que debería mostrar el ítem de menú. El argumento entero especifica el mnemónico de teclado a utilizar.
JMenuItem(Icon) JMenuItem(String) JMenuItem(String, Icon) JMenuItem(String, int)
Se puede especificar una de las
23
Jose Luis García y Noelia Méndez
constantes VK definidas en la clase KeyEvent. Por ejemplo, para especificar "a" como el mnemónico, podemos utilizar KeyEvent.VK_A. JCheckBoxMenuItem() JCheckBoxMenuItem(Icon) JCheckBoxMenuItem(String) JCheckBoxMenuItem(String, JCheckBoxMenuItem(String, boolean) JCheckBoxMenuItem(String, boolean)
Crea un ítem de menú que se parece y actúa como un checkbox. Si se especifica un icono, el ítem de menú utiliza el icono en vez del icono por defecto de los checkboxes. El argumento string, si Icon) existe, especifica el texto que debería mostrar el ítem de menú. Si se especifica true para el argumento booleano, el Icon, ítem de menú estará inicialmente seleccionado. De lo contrario el ítem de menú está desactivado.
JRadioButtonMenuItem() JRadioButtonMenuItem(Icon) JRadioButtonMenuItem(String) JRadioButtonMenuItem(String, Icon)<
void setState(boolean) boolean getState()
Crea un ítem de menú que se parece y actúa como un radio buttom. Si se especifica un icono, el ítem de menú utiliza el icono en vez del icono por defecto de los botones de radio. El argumento string, si existe, especifica el texto que debería mostrar el ítem de menú. El ítem de menú está inicialmente desactivado. Selecciona u obtiene el estado de selección de un ítem de menú.
void setEnabled(boolean)
Si el argumento es true, activa el ítem de menú, si es false lo desactiva.
void setMnemonic(char)
Selecciona la tecla alternativa para seleccionar el ítem de menú sin el ratón.
void setActionCommand(String)
Selecciona el nombre de realizada por el ítem de menú.
void addActionListener(ActionListener)
Añade un oyente de eventos al ítem de menú.
la
acción
void addItemListener(ItemListener) La mayoría de los métodos anteriores son heredados desde AbstractButton.
12.
CONCLUSIONES
Swing es un API que ofrece JFC 1.1, y representa la nueva generación de AWT. Swing amplía AWT proporcionando muchos más tipos de componentes GUI, ofreciendo implementaciones cien por cien Java puro a estos componentes y permitiendo adaptar fácilmente el aspecto y comportamiento de tales componentes, facilitando así el trabajo de los programadores. El que los componentes de Swing sean cien por cien Java puro implica que no dependen de ninguna implementación nativa de ventanas que les de soporte, y que además estén disponibles y sean consecuentes en todo tipo de plataforma.
24
Programación con Swing
Transformar programas de AWT a Swing es muy sencillo, y gracias a todos los componentes que ofrece, presenta gran cantidad de ventajas, por lo que es recomendable utilizar éste API.
25
Jose Luis García y Noelia Méndez
13. -
26
BIBLIOGRAFÍA http://www.programacion.com/java/tutorial/swing/ Manual - Programación - Java tutor Swing http://jungla.dit.upm.es/~santiago/docencia/apuntes/Swing/ Java 1.2 Al descubierto. Jaime Jaworski Sun’s Java Swing Tutorial Java Swing Tutorial (2005) Lenguaje de programación Java