Swing es un conjunto de herramientas de widgets GUI para Java . [1] Es parte de Java Foundation Classes (JFC) de Oracle : una API para proporcionar una interfaz gráfica de usuario (GUI) para programas Java.
Swing fue desarrollado para proporcionar un conjunto de componentes GUI más sofisticados que el anterior Abstract Window Toolkit (AWT) . Swing proporciona una apariencia que emula la apariencia de varias plataformas y también admite una apariencia conectable que permite que las aplicaciones tengan una apariencia no relacionada con la plataforma subyacente. Tiene componentes más potentes y flexibles que AWT. Además de los componentes familiares, como botones, casillas de verificación y etiquetas, Swing proporciona varios componentes avanzados, como paneles con pestañas, paneles de desplazamiento, árboles, tablas y listas. [2]
A diferencia de los componentes AWT, los componentes Swing no se implementan mediante código específico de la plataforma, sino que se escriben completamente en Java y, por lo tanto, son independientes de la plataforma.
En diciembre de 2008, Sun Microsystems (el predecesor de Oracle) lanzó el marco basado en CSS / FXML que pretendía que fuera el sucesor de Swing, llamado JavaFX . [3]
Las Internet Foundation Classes (IFC) fueron una biblioteca de gráficos para Java desarrollada originalmente por Netscape Communications Corporation y lanzada por primera vez el 16 de diciembre de 1996. El 2 de abril de 1997, Sun Microsystems y Netscape Communications Corporation anunciaron su intención de incorporar IFC con otras tecnologías para formar las Java Foundation Classes . [4] Las "Java Foundation Classes" fueron posteriormente renombradas como "Swing". [ aclaración necesaria ]
Swing introdujo un mecanismo que permitía modificar la apariencia de cada componente de una aplicación sin realizar cambios sustanciales en el código de la aplicación. La introducción de compatibilidad con una apariencia conectable permite que los componentes Swing emulen la apariencia de los componentes nativos y, al mismo tiempo, conserven los beneficios de la independencia de la plataforma. Swing, que originalmente se distribuía como una biblioteca descargable por separado, se ha incluido como parte de la Edición estándar de Java desde la versión 1.2. [5] Las clases y los componentes de Swing están contenidos en la jerarquía javax.swing
de paquetes .
El desarrollo del sucesor de Swing, JavaFX , comenzó en 2005 y se presentó oficialmente dos años después en JavaOne 2007. [6] JavaFX se convirtió en código abierto en 2011 y, en 2012, pasó a formar parte de la descarga de Oracle JDK. JavaFX está reemplazando a Swing debido a varias ventajas, entre ellas, ser más liviano, tener estilo CSS , controles de diseño elegantes y el uso de FXML y Scene Builder. [7] En 2018, JavaFX pasó a formar parte de OpenJDK bajo el proyecto OpenJFX para aumentar el ritmo de su desarrollo. [8]
Los miembros del equipo del cliente Java que fue responsable de Swing incluyeron a James Gosling (arquitecto), Rick Levenson (gerente), Amy Fowler y Hans Muller (líderes técnicos conjuntos), Tom Ball, Jeff Dinkins, Georges Saab, [9] Tim Prinzing, Jonni Kanerva y Jeannette Hung y Jim Graham (gráficos 2D). [10]
Swing es un marco de interfaz gráfica de usuario (GUI ) " modelo-vista-controlador " independiente de la plataforma para Java, que sigue un modelo de programación de un solo subproceso . [11] Además, este marco proporciona una capa de abstracción entre la estructura del código y la presentación gráfica de una GUI basada en Swing.
Swing es independiente de la plataforma porque está escrito completamente en Java. La documentación completa de todas las clases de Swing se puede encontrar en la Guía de API de Java para la versión 6 o en la Especificación de API de Java Platform Standard Edition 8 para la versión 8.
Swing es una arquitectura altamente modular que permite la "conexión" de varias implementaciones personalizadas de interfaces de marco específicas: los usuarios pueden proporcionar sus propias implementaciones personalizadas de estos componentes para anular las implementaciones predeterminadas utilizando el mecanismo de herencia de Java a través de LookAndFeel
.
Swing es un marco basado en componentes , cuyos componentes se derivan en última instancia de la JComponent
clase. Los objetos Swing activan eventos de forma asincrónica, tienen propiedades vinculadas y responden a un conjunto documentado de métodos específicos del componente. Los componentes Swing son componentes JavaBeans , compatibles con la especificación JavaBeans.
La gran dependencia de Swing de los mecanismos de tiempo de ejecución y los patrones de composición indirectos le permite responder en tiempo de ejecución a cambios fundamentales en sus configuraciones. Por ejemplo, una aplicación basada en Swing es capaz de intercambiar en caliente su interfaz de usuario durante el tiempo de ejecución. Además, los usuarios pueden proporcionar su propia implementación de apariencia, lo que permite cambios uniformes en la apariencia de las aplicaciones Swing existentes sin ningún cambio programático en el código de la aplicación.
El alto nivel de flexibilidad de Swing se refleja en su capacidad inherente de anular los controles de la interfaz gráfica de usuario del sistema operativo (OS) nativo para mostrarse a sí mismo. Swing "pinta" sus controles utilizando las API 2D de Java, en lugar de llamar a un conjunto de herramientas de interfaz de usuario nativa. Por lo tanto, un componente Swing no tiene un componente de interfaz gráfica de usuario del sistema operativo nativo correspondiente y es libre de mostrarse a sí mismo de cualquier forma que sea posible con las interfaces gráficas de usuario subyacentes.
Sin embargo, en esencia, cada componente Swing depende de un contenedor AWT , ya que (Swing) JComponent
extiende el contenedor (AWT). Esto permite que Swing se conecte al marco de administración de la interfaz gráfica de usuario del sistema operativo anfitrión, incluidas las asignaciones cruciales de dispositivos/pantallas y las interacciones del usuario, como las pulsaciones de teclas o los movimientos del mouse. Swing simplemente "transpone" su propia semántica (independiente del sistema operativo) sobre los componentes subyacentes (específicos del sistema operativo). Entonces, por ejemplo, cada componente Swing pinta su representación en el dispositivo gráfico en respuesta a una llamada a component.paint(), que se define en el contenedor (AWT). Pero a diferencia de los componentes AWT, que delegaron la pintura a su widget "pesado" nativo del sistema operativo, los componentes Swing son responsables de su propia representación.
Esta transposición y desacoplamiento no es meramente visual, y se extiende a la gestión y aplicación de Swing de su propia semántica independiente del SO para eventos disparados dentro de sus jerarquías de contención de componentes. En términos generales, la arquitectura Swing delega la tarea de mapear los diversos sabores de la semántica de la GUI del SO en un patrón simple, pero generalizado, al contenedor AWT. Sobre la base de esa plataforma generalizada, establece su propia semántica de GUI rica y compleja en forma de JComponent
modelo.
La biblioteca Swing hace un uso intensivo del patrón de diseño de software modelo-vista-controlador [12] , que desacopla conceptualmente los datos que se visualizan de los controles de la interfaz de usuario a través de los cuales se visualizan. Debido a esto, la mayoría de los componentes Swing tienen modelos asociados (que se especifican en términos de interfaces Java ), y los programadores pueden usar varias implementaciones predeterminadas o proporcionar las suyas propias. El marco proporciona implementaciones predeterminadas de interfaces de modelo para todos sus componentes concretos. El uso típico del marco Swing no requiere la creación de modelos personalizados, ya que el marco proporciona un conjunto de implementaciones predeterminadas que están asociadas de forma transparente, por defecto, con la clase secundaria correspondiente en la biblioteca Swing. En general, solo los componentes complejos, como tablas, árboles y, a veces, listas, pueden requerir las implementaciones de modelos personalizados en torno a las estructuras de datos específicas de la aplicación. Para tener una buena idea del potencial que hace posible la arquitectura Swing, considere la situación hipotética en la que los modelos personalizados para tablas y listas son envoltorios sobre servicios DAO y/o EJB .JComponent
Normalmente, los objetos del modelo de componentes Swing son responsables de proporcionar una interfaz concisa que define los eventos activados y las propiedades accesibles para el modelo de datos (conceptual) para que las utilice el JComponent asociado. Dado que el patrón MVC general es un patrón de relación de objetos colaborativos acoplado de forma flexible, el modelo proporciona los medios programáticos para adjuntar escuchas de eventos al objeto del modelo de datos. Estos eventos están centrados en el modelo (por ejemplo, un evento de "fila insertada" en un modelo de tabla) y la especialización de JComponent los asigna a un evento significativo para el componente GUI.
Por ejemplo, JTable
tiene un modelo llamado que describe una interfaz para que una tabla acceda a datos tabulares. Una implementación predeterminada de esto opera en una matrizTableModel
bidimensional .
El componente de vista de un JComponent de Swing es el objeto que se utiliza para representar gráficamente el control GUI conceptual. Una distinción de Swing, como marco GUI, es su dependencia de controles GUI generados mediante programación (en contraposición al uso de los controles GUI del sistema operativo host nativo). Antes de Java 6 Update 10 , esta distinción era una fuente de complicaciones al mezclar controles AWT, que utilizan controles nativos, con controles Swing en una GUI (consulte Mezcla de componentes AWT y Swing ).
Por último, en términos de composición y gestión visual, Swing favorece los diseños relativos (que especifican las relaciones posicionales entre los componentes) en lugar de los diseños absolutos (que especifican la ubicación y el tamaño exactos de los componentes). Esta preferencia por un orden visual "fluido" se debe a sus orígenes en el entorno operativo de los subprogramas que enmarcó el diseño y el desarrollo del kit de herramientas de interfaz gráfica de usuario original de Java. (Conceptualmente, esta visión de la gestión del diseño es bastante similar a la que informa la representación del contenido HTML en los navegadores y aborda el mismo conjunto de preocupaciones que motivaron la primera).
Desde las primeras versiones de Java, una parte del Abstract Window Toolkit (AWT) ha proporcionado API independientes de la plataforma para los componentes de la interfaz de usuario. En AWT, cada componente es representado y controlado por un componente nativo específico del sistema de ventanas subyacente.
Por el contrario, los componentes Swing suelen describirse como ligeros porque no requieren la asignación de recursos nativos en el conjunto de herramientas de ventanas del sistema operativo. Los componentes AWT se denominan componentes pesados . [13]
Gran parte de la API Swing es, en general, una extensión complementaria de AWT en lugar de un reemplazo directo. De hecho, cada interfaz liviana de Swing existe en última instancia dentro de un componente pesado de AWT porque todos los componentes de nivel superior en Swing ( JApplet
, JDialog
, JFrame
, y JWindow
) extienden un contenedor de nivel superior de AWT. Antes de Java 6 Update 10 , generalmente se desaconsejaba el uso de componentes livianos y pesados dentro de la misma ventana debido a incompatibilidades de orden Z. Sin embargo, las versiones posteriores de Java han solucionado estos problemas y ahora se pueden usar los componentes Swing y AWT en una GUI sin problemas de orden Z.
La funcionalidad de renderizado principal utilizada por Swing para dibujar sus componentes livianos la proporciona Java 2D , otra parte de JFC.
El Standard Widget Toolkit (SWT) es un conjunto de herramientas de la competencia desarrollado originalmente por IBM y ahora mantenido por la comunidad Eclipse . La implementación de SWT tiene más en común con los componentes pesados de AWT. Esto confiere beneficios tales como una fidelidad más precisa con el conjunto de herramientas de ventanas nativo subyacente, a costa de una mayor exposición a la plataforma nativa en el modelo de programación.
Ha habido un importante debate y especulación sobre el rendimiento de SWT versus Swing; algunos insinuaron que la fuerte dependencia de SWT de JNI lo haría más lento cuando el componente GUI y Java necesitan comunicar datos, pero más rápido en la representación cuando el modelo de datos se ha cargado en la GUI, pero esto no ha sido confirmado de ninguna manera. [14] Un conjunto bastante completo de puntos de referencia en 2005 concluyó que ni Swing ni SWT superaron claramente al otro en el caso general. [15]
Esta aplicación Swing de ejemplo crea una única ventana con "¡Hola, mundo!" dentro:
// Hola.java (Java SE 8) importar javax.swing.* ; clase pública Hola extiende JFrame { pública Hola () { super ( "Hola mundo" ); setDefaultCloseOperation ( WindowConstants . EXIT_ON_CLOSE ); agregar ( nuevo JLabel ( "¡Hola, mundo!" )); paquete (); setVisible ( verdadero ); } public static void main ( String [ ] args ) { SwingUtilities .invokeLater ( Hola :: nuevo ); } }
El primero import
incluye todas las clases e interfaces públicas del javax.swing
paquete.
La Hello
clase extends
la JFrame
clase; la JFrame
clase implementa una ventana con una barra de título y un control de cierre .
El Hello()
constructor inicializa el marco llamando primero al constructor de la superclase, pasando el parámetro "Hello World"
, que se utiliza como título de la ventana. A continuación, llama al setDefaultCloseOperation(int)
método heredado de JFrame
para establecer la operación predeterminada cuando se selecciona el control de cierre en la barra de título a WindowConstants.EXIT_ON_CLOSE
– esto hace que se JFrame
descarte cuando se cierra el marco (en lugar de simplemente ocultarlo), lo que permite que la máquina virtual Java salga y el programa finalice. A continuación, JLabel
se crea un para la cadena "Hello, world!" y se llama al add(Component)
método heredado de la Container
superclase para agregar la etiqueta al marco. El pack()
método heredado de la Window
superclase se llama para dimensionar la ventana y diseñar su contenido. El setVisible(boolean)
método heredado de la Component
superclase se llama con el parámetro booleano true
, que hace que se muestre el marco.
La main()
máquina virtual Java llama al método cuando se inicia el programa. Crea una instancia de un nuevo Hello
marco. El código utiliza el invokeLater(Runnable)
método para invocar el constructor desde el hilo de distribución de eventos de AWT para garantizar que el código se ejecute de manera segura para subprocesos . Una vez que se muestra el marco, salir del main
método no hace que el programa finalice porque el hilo de distribución de eventos permanece activo hasta que se hayan eliminado todas las ventanas de nivel superior de Swing.
El siguiente es un programa bastante simple basado en Swing. Muestra una ventana (a JFrame
) que contiene una etiqueta y un botón.
import java.awt.FlowLayout ; import javax.swing.JButton ; import javax.swing.JFrame ; import javax.swing.JLabel ; import javax.swing.WindowConstants ; import javax.swing.SwingUtilities ; public class SwingExample implements Runnable { private JFrame f ; public SwingExample () { // Crea la ventana f = new JFrame ( "¡Hola mundo!" ); // Establece el comportamiento para cuando la ventana está cerrada f .setDefaultCloseOperation ( WindowConstants .EXIT_ON_CLOSE ); // Agrega un administrador de diseño para que el botón no se coloque sobre la etiqueta f .setLayout ( new FlowLayout ()); // Agrega una etiqueta y un botón f .add ( new JLabel ( "¡ Hola , mundo!" )); f .add ( new JButton ( "¡ Presiona me!" )); } @Override public void run () { // Organiza los componentes dentro de la ventana f . pack (); // De forma predeterminada, la ventana no es visible. Hazla visible. f . setVisible ( true ); } public static void main ( String [] args ) { // Programa la aplicación para que se ejecute en el momento correcto en la cola de eventos. SwingUtilities . activateLater ( new SwingExample ()); } }
Observe cómo toda la creación de instancias y el manejo de los componentes Swing se realizan mediante la creación de una instancia de la clase, que implementa la interfaz Runnable. Esta se ejecuta luego en el subproceso de despacho de eventos mediante el uso del método SwingUtilities.invokeLater(Runnable)
), creado en el método principal (consulte Swing y seguridad de subprocesos ). Aunque el código Swing se puede ejecutar sin utilizar esta técnica (por ejemplo, al no implementar Runnable y mover todos los comandos del método run al método principal), se considera que es una buena forma, ya que Swing no es seguro para subprocesos , lo que significa que invocar recursos de varios subprocesos puede provocar interferencias de subprocesos y errores de consistencia de memoria. [16]
Los campos de texto permiten a los usuarios introducir texto o datos en la aplicación. Crear un campo de texto en Swing es muy sencillo: crea una instancia de un objeto JTextField y agrégalo a un contenedor.
importar javax.swing.* ; clase pública TextFieldExample { pública estática void main ( String [] args ) { // Crear un JFrame JFrame frame = new JFrame ( "Ejemplo de campo de texto" ); // Crea un JTextField JTextField textField = new JTextField ( 20 ); // Agrega el campo de texto al marco JFrame . add ( textField ); // Establece el tamaño del JFrame y hazlo visible frame.setSize ( 300,200 ) ; frame.setVisible ( true ) ; } }
Mejorar la funcionalidad de los campos de texto mejora la interacción del usuario. Al adjuntar interfaces DocumentListener, puede supervisar dinámicamente los cambios en el contenido del texto, lo que permite la validación, el formato o el autocompletado de los datos de entrada en tiempo real.
La validación de la entrada en un campo de texto es fundamental para garantizar la integridad de los datos y evitar errores. Swing ofrece múltiples técnicas de validación, incluidas expresiones regulares, máscaras de entrada o lógica de validación personalizada. Al implementar interfaces InputVerifier, puede definir reglas de validación específicas y ofrecer comentarios inmediatos a los usuarios cuando la entrada no es válida. [17]
En este ejemplo, dejemos que javax.swing.JFrame sea una superclase y agreguemos nuestros propios widgets (en este caso, un JButton).
importar javax.swing.JFrame ; importar javax.swing.JButton ; importar javax.swing.JOptionPane ; importar javax.swing.SwingUtilities ; importar java.awt.event.ActionListener ; importar java.awt.event.ActionEvent ; clase pública Sample extiende JFrame { privada final JButton b = nuevo JButton (); public Sample () { super (); este . setTitle ( "HelloApp" ); este . getContentPane (). setLayout ( null ); este . setBounds ( 100 , 100 , 180 , 140 ); este . add ( makeButton ()); este . setVisible ( true ); este . setDefaultCloseOperation ( EXIT_ON_CLOSE ); } privado JButton makeButton () { b . setText ( "¡Haz clic en mí!" ); b . setBounds ( 40 , 40 , 100 , 30 ); b . addActionListener ( new ActionListener () { público void actionPerformed ( ActionEvent e ) { JOptionPane . showMessageDialog ( b , "¡Hola mundo!" ); } }); return b ; } public static void main ( String [] args ) throws InvocationTargetException , InterruptedException { // Las llamadas Swing deben ser ejecutadas por el hilo de despacho de eventos. SwingUtilities .invokeAndWait (() -> new Sample ()) ; } }
El diseño se establece como nulo utilizando el Container.setLayout(LayoutManager)
método ya que JFrame utiliza java.awt.BorderLayout como su administrador de diseño predeterminado. Con BorderLayout, todo lo que se agrega al contenedor se coloca en el centro y se estira para acomodar otros widgets. Por supuesto, la mayoría de las aplicaciones GUI del mundo real preferirían usar un administrador de diseño en lugar de colocar todo en coordenadas absolutas. [18]
Las Java Foundation Classes son ahora fundamentales para la plataforma Java 2 e incluyen: El conjunto de componentes de interfaz gráfica de usuario de Project Swing, Arrastrar y soltar, API de Java 2D que proporciona nuevas capacidades de gráficos 2D y AWT, así como compatibilidad con impresión, La interfaz de apariencia y funcionamiento de Java, Una nueva API de accesibilidad
{{cite web}}
: CS1 maint: URL no apta ( enlace )Es difícil dar una regla general en la que SWT superaría a Swing, o viceversa. En algunos entornos (por ejemplo, Windows), SWT es un ganador. En otros (Linux,
VMware
que aloja Windows), Swing y su optimización de redibujado superan a SWT significativamente. Las diferencias en el rendimiento son significativas: los factores de 2 y más son comunes, en cualquier dirección.