Swing (Java) - Swing (Java)

Widgets Swing de exemplo em Java

Swing é um kit de ferramentas de widget GUI para Java . É parte do Oráculo de classes Java Foundation (JFC) - uma API para fornecer uma interface gráfica do usuário (GUI) para programas Java.

O Swing foi desenvolvido para fornecer um conjunto mais sofisticado de componentes GUI do que o Abstract Window Toolkit (AWT) anterior . O Swing fornece uma aparência que emula a aparência de várias plataformas e também oferece uma aparência conectável que permite que os aplicativos tenham uma aparência não relacionada à plataforma subjacente. Possui componentes mais poderosos e flexíveis do que AWT. Além de componentes familiares, como botões, caixas de seleção e rótulos, o Swing fornece vários componentes avançados, como painel com guias, painéis de rolagem, árvores, tabelas e listas.

Ao contrário dos componentes AWT, os componentes Swing não são implementados pelo código específico da plataforma. Em vez disso, eles são escritos inteiramente em Java e, portanto, são independentes de plataforma.

Em dezembro de 2008, a Sun Microsystems (predecessora da Oracle) lançou o framework baseado em CSS / FXML que pretendia ser o sucessor do Swing, chamado JavaFX .

História

As Internet Foundation Classes (IFC) eram uma biblioteca gráfica para Java originalmente desenvolvida pela Netscape Communications Corporation e lançada pela primeira vez em 16 de dezembro de 1996. Em 2 de abril de 1997, a Sun Microsystems e a Netscape Communications Corporation anunciaram sua intenção de incorporar IFC com outras tecnologias para formar as classes Java Foundation . As "Java Foundation Classes" foram posteriormente renomeadas para "Swing".

O Swing introduziu um mecanismo que permitia que a aparência de cada componente em um aplicativo fosse alterada sem fazer mudanças substanciais no código do aplicativo. A introdução de suporte para uma aparência plugável permite que os componentes Swing emulem a aparência de componentes nativos enquanto mantém os benefícios da independência de plataforma. Distribuído originalmente como uma biblioteca para download separadamente, o Swing foi incluído como parte do Java Standard Edition desde o lançamento 1.2. As classes e componentes Swing estão contidos na hierarquia do javax.swing pacote .

O desenvolvimento do sucessor do Swing, JavaFX , começou em 2005 e foi oficialmente apresentado dois anos depois no JavaOne 2007. O JavaFX teve o código aberto em 2011 e, em 2012, tornou-se parte do download do Oracle JDK. O JavaFX está substituindo o Swing devido a várias vantagens, incluindo ser mais leve, ter estilo CSS , controles de design elegantes e o uso de FXML e Scene Builder. Em 2018, o JavaFX passou a fazer parte do OpenJDK no projeto OpenJFX para aumentar o ritmo de seu desenvolvimento.

Os membros da equipe do cliente Java responsável pelo Swing incluíam James Gosling (arquiteto), Rick Levenson (gerente), Amy Fowler & Hans Muller (líderes co-técnicos), Tom Ball, Jeff Dinkins, Georges Saab, Tim Prinzing, Jonni Kanerva e Jeannette Hung & Jim Graham (gráficos 2D).

Arquitetura

Swing é uma estrutura GUI independente de plataforma " model-view-controller " para Java, que segue um modelo de programação de thread único . Além disso, essa estrutura fornece uma camada de abstração entre a estrutura do código e a apresentação gráfica de uma GUI baseada em Swing.

Fundações

O Swing é independente de plataforma porque é totalmente escrito em Java. A documentação completa para todas as classes Swing pode ser encontrada no Java API Guide para a versão 6 ou na Java Platform Standard Edition 8 API Specification para a versão 8.

Extensível

Swing é uma arquitetura altamente modular, que permite o "plugging" de várias implementações customizadas de interfaces de estrutura especificadas: Os usuários podem fornecer suas próprias implementações customizadas desses componentes para substituir as implementações padrão usando o mecanismo de herança do Java via javax.swing.LookAndFeel.

Swing é uma estrutura baseada em componentes , cujos componentes são todos derivados da javax.swing.JComponentclasse. Os objetos Swing disparam eventos de forma assíncrona, têm propriedades vinculadas e respondem a um conjunto documentado de métodos específicos para o componente. Os componentes Swing são componentes JavaBeans , em conformidade com a especificação JavaBeans .

Configurável

A forte dependência do Swing em mecanismos de tempo de execução e padrões de composição indireta permite que ele responda em tempo de execução a mudanças fundamentais em suas configurações. Por exemplo, um aplicativo baseado em Swing é capaz de fazer hot swap de sua interface de usuário durante o tempo de execução. Além disso, os usuários podem fornecer sua própria implementação de aparência, o que permite mudanças uniformes na aparência de aplicativos Swing existentes sem qualquer alteração programática no código do aplicativo.

UI leve

O alto nível de flexibilidade do Swing é refletido em sua capacidade inerente de substituir os controles de GUI do sistema operacional host nativo (SO) para exibição de si mesmo. O Swing "pinta" seus controles usando APIs Java 2D, em vez de chamar um kit de ferramentas de interface de usuário nativo. Portanto, um componente Swing não tem um componente GUI do SO nativo correspondente e é livre para renderizar a si mesmo de qualquer maneira possível com as GUIs gráficas subjacentes.

No entanto, em sua essência, cada componente do Swing depende de um contêiner AWT , uma vez que (do Swing) JComponentestende o contêiner (AWT). Isso permite que o Swing se conecte à estrutura de gerenciamento da GUI do host OS, incluindo os mapeamentos de dispositivo / tela cruciais e interações do usuário, como pressionamentos de teclas ou movimentos do mouse. O Swing simplesmente "transpõe" sua própria semântica (independente do sistema operacional) sobre os componentes subjacentes (específicos do sistema operacional). Assim, por exemplo, cada componente Swing pinta sua representação no dispositivo gráfico em resposta a uma chamada para component.paint (), que é definido em (AWT) Container. Mas, ao contrário dos componentes AWT, que delegavam a pintura ao widget "pesado" nativo do sistema operacional, os componentes Swing são responsáveis ​​por sua própria renderização.

Essa transposição e desacoplamento não são meramente visuais e se estendem ao gerenciamento e à aplicação do Swing de sua própria semântica independente do sistema operacional para eventos disparados dentro de suas hierarquias de contenção de componentes. De um modo geral, a arquitetura Swing delega a tarefa de mapear os vários sabores da semântica da GUI do SO em um padrão simples, mas generalizado, para o contêiner AWT. Com base nessa plataforma generalizada, ele estabelece sua própria semântica de GUI rica e complexa na forma do JComponentmodelo.

Fracamente acoplado e MVC

A biblioteca Swing faz uso intenso do padrão de design do software model-view-controller , que conceitualmente desacopla os dados que estão sendo visualizados dos controles da interface do usuário por meio dos quais são visualizados. Por causa disso, a maioria dos componentes Swing tem modelos associados (que são especificados em termos de interfaces Java ) e os programadores podem usar várias implementações padrão ou fornecer suas próprias. A estrutura fornece implementações padrão de interfaces de modelo para todos os seus componentes concretos. O uso típico da estrutura Swing não requer a criação de modelos customizados, pois a estrutura fornece um conjunto de implementações padrão que são transparentemente, por padrão, associadas à classe filha correspondente na biblioteca Swing. Em geral, apenas componentes complexos, como tabelas, árvores e, às vezes, listas, podem exigir as implementações de modelo personalizado em torno das estruturas de dados específicas do aplicativo. Para ter uma boa noção do potencial que a arquitetura Swing torna possível, considere a situação hipotética em que os modelos personalizados para tabelas e listas são invólucros de serviços DAO e / ou EJB . JComponent

Normalmente, os objetos do modelo de componente Swing são responsáveis ​​por fornecer uma interface concisa definindo eventos disparados e propriedades acessíveis para o modelo de dados (conceitual) para uso pelo JComponent associado. Dado que o padrão MVC geral é um padrão de relacionamento de objeto colaborativo fracamente acoplado, o modelo fornece os meios programáticos para anexar ouvintes de evento ao objeto de modelo de dados. Normalmente, esses eventos são centrados no modelo (ex: um evento de "linha inserida" em um modelo de tabela) e são mapeados pela especialização JComponent em um evento significativo para o componente GUI.

Por exemplo, o JTabletem um modelo chamado TableModelque descreve uma interface de como uma tabela acessa os dados tabulares. Uma implementação padrão disso opera em uma matriz bidimensional .

O componente de visualização de um Swing JComponent é o objeto usado para representar graficamente o controle GUI conceitual. Uma distinção do Swing, como uma estrutura de GUI, está em sua confiança em controles de GUI renderizados programaticamente (em oposição ao uso de controles de GUI do sistema operacional nativo). Antes do Java 6 Update 10 , essa distinção era uma fonte de complicações ao misturar controles AWT, que usam controles nativos, com controles Swing em uma GUI (consulte Misturando componentes AWT e Swing ).

Finalmente, em termos de composição visual e gerenciamento, o Swing favorece layouts relativos (que especificam as relações posicionais entre os componentes) em oposição aos layouts absolutos (que especificam a localização exata e o tamanho dos componentes). Essa tendência para a ordenação visual "fluida" se deve às suas origens no ambiente operacional do miniaplicativo que moldou o design e o desenvolvimento do kit de ferramentas GUI Java original. (Conceitualmente, essa visão do gerenciamento de layout é bastante semelhante àquela que informa a renderização de conteúdo HTML em navegadores e aborda o mesmo conjunto de preocupações que motivou a primeira.)

Relacionamento com AWT

Hierarquia de classes AWT e Swing

Desde as primeiras versões do Java, uma parte do Abstract Window Toolkit (AWT) fornece APIs independentes de plataforma para componentes de interface do usuário. No AWT, cada componente é renderizado e controlado por um componente de mesmo nível nativo específico para o sistema de janelas subjacente.

Por outro lado, os componentes Swing são frequentemente descritos como leves porque não requerem alocação de recursos nativos no kit de ferramentas de janelas do sistema operacional. Os componentes AWT são chamados de componentes pesados .

Muito da API Swing é geralmente uma extensão complementar do AWT, em vez de uma substituição direta. Na verdade, cada interface leve balanço em última análise, existe dentro de um componente pesado AWT porque todos os componentes de nível superior no Swing ( JApplet, JDialog, JFrame, e JWindow) estender um recipiente de nível superior AWT. Antes do Java 6 Update 10 , o uso de componentes leves e pesados ​​dentro da mesma janela era geralmente desencorajado devido a incompatibilidades de ordem Z. No entanto, versões posteriores do Java corrigiram esses problemas e os componentes Swing e AWT agora podem ser usados ​​em uma GUI sem problemas de ordem Z.

A principal funcionalidade de renderização usada pelo Swing para desenhar seus componentes leves é fornecida pelo Java 2D , outra parte do JFC.

Relacionamento com SWT

O Standard Widget Toolkit (SWT) é um kit de ferramentas concorrente originalmente desenvolvido pela IBM e agora mantido pela comunidade Eclipse . A implementação do SWT tem mais em comum com os componentes pesados ​​do AWT. Isso confere benefícios como fidelidade mais precisa com o kit de ferramentas de janela nativo subjacente, ao custo de uma maior exposição à plataforma nativa no modelo de programação.

Tem havido um debate significativo e especulação sobre o desempenho do SWT versus Swing; alguns sugeriram que a forte dependência do SWT em JNI o tornaria mais lento quando o componente GUI e Java precisassem comunicar dados, mas mais rápido na renderização quando o modelo de dados fosse carregado na GUI, mas isso não foi confirmado de nenhuma forma. Um conjunto bastante completo de benchmarks em 2005 concluiu que nem o Swing nem o SWT superaram claramente o outro no caso geral.

Exemplos

Olá Mundo

Este exemplo de aplicativo Swing cria uma única janela com "Olá, 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();
    }
}

O primeiro importinclui todas as classes públicas e interfaces do javax.swingpacote.

A Helloclasse extendsa JFrameclasse; a JFrameclasse implementa uma janela com uma barra de título e um controle de fechamento .

O Hello() construtor inicializa o quadro chamando primeiro o construtor da superclasse, passando o parâmetro "hello", que é usado como título da janela. Em seguida, ele chama o setDefaultCloseOperation(int)método herdado de JFramepara definir a operação padrão quando o controle de fechamento na barra de título é selecionado para WindowConstants.EXIT_ON_CLOSE - isso faz com que o JFrameseja descartado quando o quadro for fechado (em oposição a simplesmente oculto), o que permite que a máquina virtual Java para sair e o programa para terminar. Em seguida, um JLabelé criado para a string "Hello, world!" e o add(Component)método herdado da Containersuperclasse é chamado para adicionar o rótulo ao quadro. O pack()método herdado da Windowsuperclasse é chamado para dimensionar a janela e organizar seu conteúdo.

O main()método é chamado pela máquina virtual Java quando o programa é iniciado. Ele instancia um novo Helloquadro e faz com que ele seja exibido chamando o setVisible(boolean)método herdado da Componentsuperclasse com o parâmetro booleano true. Depois que o quadro é exibido, sair do mainmétodo não faz com que o programa seja encerrado porque o encadeamento de despacho de evento AWT permanece ativo até que todas as janelas de nível superior do Swing tenham sido descartadas.

Janela com botão

O código de exemplo básico em execução no Windows 7

O que se segue é um programa bastante simples baseado em Swing. Ele exibe uma janela (a JFrame) contendo um rótulo e um botão.

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 como toda a instanciação e manipulação de componentes Swing são feitas criando uma instância da classe, que implementa a interface Runnable. Em seguida, ele é executado no Event Dispatch Thread com o uso do método SwingUtilities.invokeLater(Runnable)), criado no método principal (consulte Swing e segurança de thread ). Embora o código Swing possa ser executado sem o uso desta técnica (por exemplo, não implementando Runnable e movendo todos os comandos do método run para o método principal), ele é considerado de boa forma, pois o Swing não é thread-safe , o que significa que chamar recursos de vários encadeamentos pode resultar em interferência de encadeamento e erros de consistência de memória.

Outro exemplo

Neste exemplo, deixe javax.swing.JFrame ser uma superclasse e adicione nosso (s) próprio (s) widget (s) a ela (neste caso, um 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());
	}
}

O layout é definido como nulo usando o Container.setLayout(LayoutManager)método, já que JFrame usa java.awt.BorderLayout como seu gerenciador de layout padrão. Com o BorderLayout, qualquer coisa adicionada ao contêiner é colocada no centro e esticada para acomodar quaisquer outros widgets. Claro, a maioria dos aplicativos GUI do mundo real prefere usar um gerenciador de layout em vez de colocar tudo em coordenadas absolutas.

Veja também

Referências

Citações

Fontes

links externos