Swing es un kit de herramientas de widget 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 sofisticado 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. En cambio, están escritos 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 ser el sucesor de Swing, llamado JavaFX . [3]
Internet Foundation Classes (IFC) era 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 Forman las clases básicas de Java . [4] Las "Clases de Fundamentos de Java" pasaron a llamarse posteriormente "Swing".
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 soporte para una apariencia conectable permite que los componentes Swing emulen la apariencia de los componentes nativos y al mismo tiempo conservan los beneficios de la independencia de la plataforma. Distribuido originalmente como una biblioteca descargable por separado, Swing se ha incluido como parte de Java Standard Edition desde la versión 1.2. [5] Las clases y 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 fue de 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, que incluyen 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 responsable de Swing incluyeron a James Gosling (Arquitecto), Rick Levenson (gerente), Amy Fowler y Hans Muller (directores co-técnicos), 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 GUI de " 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á completamente escrito en Java. La documentación completa para todas las clases Swing se puede encontrar en la Guía API de Java para la Versión 6 o en la Especificación de API 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 que cumplen con la especificación JavaBeans.
La gran dependencia de Swing de los mecanismos de ejecución y los patrones de composición indirectos le permite responder en tiempo de ejecución a cambios fundamentales en su configuración. 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 para anular los controles GUI del sistema operativo (SO) nativo para mostrarse. Swing "pinta" sus controles utilizando las API 2D de Java, en lugar de llamar a un kit de herramientas de interfaz de usuario nativo. Por lo tanto, un componente Swing no tiene un componente GUI del sistema operativo nativo correspondiente y es libre de representarse a sí mismo de cualquier forma posible con las GUI gráficas subyacentes.
Sin embargo, en esencia, cada componente de 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 GUI del sistema operativo host, incluidas las asignaciones cruciales de dispositivo/pantalla y las interacciones del usuario, como presionar teclas o 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 componente.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 sistema operativo para eventos desencadenados dentro de las jerarquías de contención de sus componentes. En términos generales, la arquitectura Swing delega la tarea de mapear los diversos tipos de semántica de la GUI del sistema operativo en un patrón simple, pero generalizado, al contenedor AWT. Sobre la base de esa plataforma generalizada, establece su propia semántica 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 ven de los controles de la interfaz de usuario a través de los cuales se ven. 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 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 y predeterminada con la clase secundaria correspondiente en la biblioteca Swing. En general, sólo los componentes complejos, como tablas, árboles y, a veces, listas, pueden requerir 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 la arquitectura Swing hace posible, considere la situación hipotética en la que los modelos personalizados para tablas y listas son contenedores para 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 propiedades accesibles para el modelo de datos (conceptual) para uso del JComponent asociado. Dado que el patrón MVC general es un patrón de relación de objetos colaborativos débilmente acoplados, el modelo proporciona los medios programáticos para adjuntar detectores de eventos al objeto del modelo de datos. Normalmente, estos eventos se centran en el modelo (por ejemplo, un evento de "fila insertada" en un modelo de tabla) y la especialización JComponent los asigna a un evento significativo para el componente GUI.
Por ejemplo, JTable
tiene un modelo llamado TableModel
que describe una interfaz sobre cómo una tabla accedería a los datos tabulares. Una implementación predeterminada de esto opera en una matriz bidimensional .
El componente de vista de un Swing JComponent es el objeto utilizado para representar gráficamente el control GUI conceptual. Una distinción de Swing, como marco de GUI, es su dependencia de los controles de GUI renderizados mediante programación (a diferencia del uso de los controles de 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 usan controles nativos, con controles Swing en una GUI (consulte Mezcla de componentes AWT y Swing ).
Finalmente, 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 exacta y el tamaño de los componentes). Este sesgo hacia el ordenamiento visual "fluido" se debe a sus orígenes en el entorno operativo del subprograma que enmarcó el diseño y desarrollo del kit de herramientas GUI de Java original. (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 a menudo se describen como livianos porque no requieren la asignación de recursos nativos en el conjunto de herramientas de ventanas del sistema operativo. Los componentes AWT se conocen como componentes pesados . [13]
Gran parte de la API Swing es generalmente una extensión complementaria de la AWT en lugar de un reemplazo directo. De hecho, cada interfaz ligera de Swing existe en última instancia dentro de un componente pesado de AWT porque todos los componentes de nivel superior en Swing ( JApplet
,, y ) 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, versiones posteriores de Java han solucionado estos problemas y ahora se pueden usar componentes Swing y AWT en una GUI sin problemas de orden Z.JDialog
JFrame
JWindow
La funcionalidad principal de renderizado utilizada por Swing para dibujar sus componentes livianos la proporciona Java 2D , otra parte de JFC.
El Standard Widget Toolkit (SWT) es un kit de herramientas competitivo 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 nativas 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 frente a Swing; algunos insinuaron que la fuerte dependencia de SWT en 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 se ha confirmado de ninguna manera. [14] Un conjunto bastante exhaustivo de puntos de referencia en 2005 concluyó que ni Swing ni SWT claramente superaron al otro en el caso general. [15]
Esta aplicación Swing de ejemplo crea una única ventana con "¡Hola, mundo!" adentro:
// Hola.java (Java SE 8) import javax.swing.* ; clase pública Hola extiende JFrame { Hola público () { super ( "Hola mundo" ); setDefaultCloseOperation ( Constantes de ventana . EXIT_ON_CLOSE ); add ( new JLabel ( "¡Hola mundo!" )); embalar (); setVisible ( verdadero ); } público estático vacío principal ( 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 y pasando el parámetro "Hello World"
, que se utiliza como título de la ventana. Luego 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 WindowConstants.EXIT_ON_CLOSE
; esto hace que JFrame
se elimine cuando el marco está cerrado (en lugar de simplemente ocultarse), lo que permite que la máquina virtual Java para salir y el programa para terminar. A continuación, JLabel
se crea un para la cadena "¡Hola, mundo!" y se llama al add(Component)
método heredado de la Container
superclase para agregar la etiqueta al marco. Se llama al pack()
método heredado de la Window
superclase 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
, lo 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 al constructor desde el subproceso de distribución de eventos 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.
importar java.awt.FlowLayout ; importar javax.swing.JButton ; importar javax.swing.JFrame ; importar javax.swing.JLabel ; importar javax.swing.WindowConstants ; importar javax.swing.SwingUtilities ; la clase pública SwingExample implementa Runnable { JFrame privado f ; public SwingExample () { // Crea la ventana f = new JFrame ( "¡Hola mundo!" ); // Establece el comportamiento cuando la ventana está cerrada f . setDefaultCloseOperation ( Constantes de ventana . EXIT_ON_CLOSE ); // Agrega un administrador de diseño para que el botón no se coloque encima de la etiqueta f . setLayout ( nuevo FlowLayout ()); // Agrega una etiqueta y un botón f . add ( new JLabel ( "¡Hola mundo!" )); F. add ( new JButton ( "¡Presioname!" )); } @Override public void run () { // Organiza los componentes dentro de la ventana f . embalar (); // Por defecto, la ventana no es visible. Hazlo visible. F. setVisible ( verdadero ); } public static void main ( String [] args ) { // Programa la aplicación para que se ejecute en el momento correcto en la cola de eventos. SwingUtilidades . invokeLater ( nuevo SwingExample ()); } }
Observe cómo todas las instancias y el manejo de los componentes Swing se realizan creando una instancia de la clase, que implementa la interfaz Runnable. Luego, esto se ejecuta en el subproceso de envío 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 de ejecución al método principal), se considera una buena forma, ya que Swing no es seguro para subprocesos , lo que significa que La invocación de recursos de varios subprocesos puede provocar interferencias entre subprocesos y errores de coherencia de la memoria. [dieciséis]
En este ejemplo, permita que javax.swing.JFrame sea una superclase y agréguele 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 ; La muestra de clase pública extiende JFrame { JButton final privado b = nuevo JButton (); Muestra pública () { super (); este . setTitle ( "HolaAplicación" ); este . getPanel de contenido (). setLayout ( nulo ); este . establecerLímites ( 100 , 100 , 180 , 140 ); este . agregar ( hacerBotón ()); este . setVisible ( verdadero ); este . setDefaultCloseOperation ( EXIT_ON_CLOSE ); } JButton privado makeButton () { b . setText ( "¡Haz clic en mí!" ); b . establecerLímites ( 40 , 40 , 100 , 30 ); b . addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent e ) { JOptionPane . showMessageDialog ( b , "¡Hola mundo!" ); } }); devolver b ; } public static void main ( String [] args ) lanza InvocationTargetException , InterruptedException { // Las llamadas swing deben ser ejecutadas por el hilo de distribución de eventos. SwingUtilidades . invokeAndWait (() -> nueva muestra ()); } }
El diseño se establece en nulo usando el Container.setLayout(LayoutManager)
método ya que JFrame usa 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. [17]
Las clases básicas de Java ahora son fundamentales para la plataforma Java 2 e incluyen: el conjunto de componentes GUI de Project Swing, arrastrar y soltar, API Java 2D que proporciona nuevas capacidades de gráficos 2D y AWT, así como soporte de impresión, la interfaz de apariencia y sensación de Java. , Una nueva API de accesibilidad
{{cite web}}
: Mantenimiento CS1: 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 significativamente a SWT.
Las diferencias en el rendimiento son significativas: los factores de 2 y más son comunes, en cualquier dirección.