Swing (Java) - Swing (Java)

Ejemplo de widgets Swing en Java

Swing es un kit de herramientas de widget de GUI para Java . Es parte de Oracle 's Java Foundation Classes (JFC) - una API para proporcionar una interfaz gráfica de usuario (GUI) para programas Java.

Swing fue desarrollado para proporcionar un conjunto más sofisticado de componentes GUI 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 y sensación que no están relacionadas 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.

A diferencia de los componentes de AWT, los componentes de Swing no se implementan mediante un 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 .

Historia

Los Foundation Classes de Internet (CFI) eran una biblioteca de gráficos para Java desarrollado originalmente por Netscape Communications Corporation y lanzado por primera vez el 16 de diciembre de 1996. El 2 de abril de 1997, Sun Microsystems y Netscape Communications Corporation ha anunciado su intención de incorporar la IFC con otras tecnologías a forman las clases fundamentales de Java . Las "Clases Fundamentales de Java" fueron posteriormente renombradas como "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 y sensación conectables permite que los componentes de Swing emulen la apariencia de los componentes nativos mientras aún 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. Las clases y componentes de Swing se encuentran en la jerarquía de javax.swing paquetes .

El desarrollo del sucesor de Swing, JavaFX , comenzó en 2005 y se presentó oficialmente dos años más tarde en JavaOne 2007. JavaFX fue de código abierto en 2011 y, en 2012, se convirtió en 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. En 2018, JavaFX se hizo parte de OpenJDK bajo el proyecto OpenJFX para aumentar el ritmo de su desarrollo.

Los miembros del equipo de Java Client que era responsable de Swing incluían a James Gosling (arquitecto), Rick Levenson (gerente), Amy Fowler y Hans Muller (líderes co-técnicos), Tom Ball, Jeff Dinkins, Georges Saab, Tim Prinzing, Jonni Kanerva y Jeannette Hung y Jim Graham (Gráficos 2D).

Arquitectura

Swing es un marco de GUI de " modelo-vista-controlador " independiente de la plataforma para Java, que sigue un modelo de programación de un solo subproceso . 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.

Cimientos

Swing es independiente de la plataforma porque está completamente escrito en Java. La documentación completa para todas las clases de Swing se puede encontrar en la Guía de API de Java para la Versión 6 o la Especificación de API de Java Platform Standard Edition 8 para la Versión 8.

Extensible

Swing es una arquitectura altamente modular, que permite "conectar" varias implementaciones personalizadas de interfaces de marco especificadas: 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 javax.swing.LookAndFeel.

Swing es un marco basado en componentes , cuyos componentes se derivan en última instancia de la javax.swing.JComponentclase. 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 .

Configurable

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.

Interfaz de usuario ligera

El alto nivel de flexibilidad de Swing se refleja en su capacidad inherente para anular los controles GUI del sistema operativo (SO) nativo del host para mostrarse a sí mismo. Swing "pinta" sus controles utilizando las API 2D de Java, en lugar de llamar a un juego de herramientas de interfaz de usuario nativo. Por lo tanto, un componente de Swing no tiene un componente de GUI de SO nativo correspondiente y es libre de renderizarse de cualquier manera que sea posible con las GUI de gráficos subyacentes.

Sin embargo, en su esencia, cada componente de Swing se basa en un contenedor AWT , ya que el contenedor (de Swing) se JComponentextiende (AWT). Esto permite que Swing se conecte al marco de gestión de la GUI del sistema operativo host, 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 de Swing pinta su interpretación en el dispositivo gráfico en respuesta a una llamada a component.paint (), que se define en (AWT) Container. 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 administración y aplicación de Swing de su propia semántica independiente del sistema operativo 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 sistema operativo en un patrón simple, pero generalizado, para el contenedor AWT. Sobre la base de esa plataforma generalizada, establece su propia semántica GUI rica y compleja en la forma del JComponentmodelo.

Acoplado libremente y MVC

La biblioteca Swing hace un uso intensivo del patrón de diseño del software modelo-vista-controlador , que conceptualmente desacopla 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 de 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 manera 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 implementaciones de modelos personalizados alrededor de 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 los servicios DAO y / o EJB . JComponent

Normalmente, los objetos del modelo de componente Swing son responsables de proporcionar una interfaz concisa que define los eventos activados y propiedades accesibles para el modelo de datos (conceptual) para que lo utilice el JComponent asociado. Dado que el patrón MVC general es un patrón de relación de objeto colaborativo débilmente acoplado, el modelo proporciona los medios programáticos para adjuntar detectores de eventos al objeto del modelo de datos. Por lo general, 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, JTabletiene un modelo llamado TableModelque describe una interfaz de 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 que se utiliza para representar gráficamente el control de la GUI conceptual. Una distinción de Swing, como marco de GUI, es su dependencia de los controles de GUI representados 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 visual y administración, Swing favorece los diseños relativos (que especifican las relaciones posicionales entre los componentes) en contraposición a 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 juego de herramientas GUI de Java original. (Conceptualmente, esta vista 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).

Relación con AWT

Jerarquía de clases AWT y Swing

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 renderizado y controlado por un componente de pares nativo específico del sistema de ventanas subyacente.

Por el contrario, los componentes de Swing a menudo se describen como livianos porque no requieren la asignación de recursos nativos en el kit de herramientas de ventanas del sistema operativo. Los componentes AWT se denominan componentes de peso pesado .

Gran parte de la API Swing es generalmente una extensión complementaria del AWT en lugar de un reemplazo directo. De hecho, cada interfaz ligera oscilación existe en última instancia dentro de un componente de peso pesado AWT porque todos los componentes de nivel superior de Swing ( JApplet, JDialog, JFrame, y JWindow) se extienden un contenedor de nivel superior AWT. Antes de Java 6 Update 10 , generalmente se desaconsejaba el uso de componentes ligeros 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 los componentes Swing y AWT ahora se pueden usar en una GUI sin problemas de orden Z.

Java 2D , otra parte de JFC, proporciona la funcionalidad de renderizado principal que utiliza Swing para dibujar sus componentes ligeros .

Relación con SWT

El kit de herramientas de widget estándar (SWT) es un kit de herramientas de la competencia desarrollado originalmente por IBM y ahora mantenido por la comunidad de Eclipse . La implementación de SWT tiene más en común con los componentes pesados ​​de AWT. Esto confiere beneficios como una fidelidad más precisa con el kit de herramientas de ventanas nativas subyacentes, a costa de una mayor exposición a la plataforma nativa en el modelo de programación.

Ha habido un gran debate y especulación sobre el rendimiento de SWT frente a 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 renderización cuando el modelo de datos se ha cargado en la GUI, pero esto no se ha confirmado de ninguna manera. Un conjunto bastante completo de puntos de referencia en 2005 concluyó que ni Swing ni SWT superaron claramente al otro en el caso general.

Ejemplos de

Hola Mundo

Esta aplicación Swing de ejemplo crea una ventana única con "¡Hola, mundo!" dentro:

// Hello.java (Java SE 5)
import javax.swing.*;

public class Hello extends JFrame {
    public Hello() {
        super("hello");
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.add(new JLabel("Hello, world!"));
        this.pack();
        this.setVisible(true);
    }

    public static void main(final String[] args) {
        new Hello();
    }
}

El primero importincluye todas las clases e interfaces públicas del javax.swingpaquete.

La Helloclase extendsla JFrameclase; la JFrameclase implementa una ventana con una barra de título y un control cercano .

El Hello() constructor inicializa el marco llamando primero al constructor de la superclase, pasando el parámetro "hello", que se usa como título de la ventana. Luego llama al setDefaultCloseOperation(int)método heredado de JFramepara establecer la operación predeterminada cuando se selecciona el control de cierre en la barra de título WindowConstants.EXIT_ON_CLOSE ; esto hace JFrameque se elimine cuando el marco está cerrado (en lugar de simplemente oculto), lo que permite que la máquina virtual Java para salir y el programa para terminar. A continuación, JLabelse crea un para la cadena "¡Hola, mundo!" y se llama al add(Component)método heredado de la Containersuperclase para agregar la etiqueta al marco. El pack()método heredado de la Windowsuperclase se llama para dimensionar la ventana y diseñar su contenido.

La main()máquina virtual Java llama al método cuando se inicia el programa. Se crea la instancia de un nuevo Hellomarco y hace que se visualiza mediante una llamada al setVisible(boolean)método heredado de la Componentsuperclase con el parámetro booleano true. Una vez que se muestra el marco, salir del mainmétodo no hace que el programa termine porque el subproceso de despacho de eventos AWT permanece activo hasta que se eliminan todas las ventanas de nivel superior de Swing.

Ventana con botón

El código de ejemplo básico que se ejecuta en Windows 7

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 {

    @Override
    public void run() {
        // Create the window
        JFrame f = new JFrame("Hello, !");
        // Sets the behavior for when the window is closed
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        // Add a layout manager so that the button is not placed on top of the label
        f.setLayout(new FlowLayout());
        // Add a label and a button
        f.add(new JLabel("Hello, world!"));
        f.add(new JButton("Press me!"));
        // Arrange the components inside the window
        f.pack();
        // By default, the window is not visible. Make it visible.
        f.setVisible(true);
    }
 
    public static void main(String[] args) {
        SwingExample se = new SwingExample();
        // Schedules the application to be run at the correct time in the event queue.
        SwingUtilities.invokeLater(se);
    }

}

Observe cómo todas las instancias y el manejo de los componentes de Swing se realizan mediante la creación de una instancia de la clase, que implementa la interfaz Runnable. Esto luego 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 usar 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 que es 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 en los subprocesos y errores de coherencia de la memoria.

Otro ejemplo

En este ejemplo, dejemos que javax.swing.JFrame sea una superclase y agreguemos nuestros propios widgets (en este caso, un JButton).

import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Sample extends JFrame {
	private final JButton b = new JButton();

	public Sample() {
		super();
		this.setTitle("HelloApp");
		this.getContentPane().setLayout(null);
		this.setBounds(100, 100, 180, 140);
		this.add(makeButton());
		this.setVisible(true);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	private JButton makeButton() {
		b.setText("Click me!");
		b.setBounds(40, 40, 100, 30);
		b.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(b, "Hello World!");
			}
		});
		return b;
	}

	public static void main(String[] args) {
		// Swing calls must be run by the event dispatching thread.
		SwingUtilities.invokeAndWait(() -> new Sample());
	}
}

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 cualquier otro widget. 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.

Ver también

Referencias

Citas

Fuentes

enlaces externos