Pluggable Look-and-feel com Swing

 

O objetivo deste artigo é descrever com detalhes um recurso disponível no pacote Swing: a Pluggable Look-and-feel, que determina como os componentes serão renderizados no momento de sua exibição.

 

Introdução

Os look-and-feels, para quem ainda não os conhecem, são objetos que ao serem configurados na aplicação, modificam o modo como o usuário irá interagir ou visualizar a interface gráfica da mesma.

 

Todos percebem, ao começar a trabalhar com java, que suas aplicações possuem componentes um pouco diferentes dos presentes no sistema operacional, no que tangem as dimensões, cores, bordas, etc. Enfim, não querendo muito entrar em detalhes quanto o design dos componentes, o que importa neste artigo é que isso pode ser mudado!

 

O pacote javax.swing.* possui um conjunto de ferramentas que permite ao programador definir qual será o look-and-feel da aplicação. Caso não defina nenhum, o próprio swing cuidará de selecioná-lo.

 

É necessário frisar também que a classe LookAndFell (javax.swing.LookAndFeel) é abstrata, o que significa que ela é apenas um “suporte” às diversas classes que representam os concretos look-and-feels utilizados em aplicações. Há também a possibilidade de criar um look-and-feel customizado.

 

Alterando o look-and-feel de uma aplicação

É interessante destacar que, tendo a interface gráfica montada e compilada, para se alterar o look-and-feel não é necessário nenhuma alteração em seu código! Apenas uma chamada para o novo L&F é suficiente para que tudo seja alterado, como mostra a listagem 1.

 

public static void main(String[] args) {

        try{                   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        } catch(Exception e){

               System.out.println("Não foi possível alterar a L&F");

        }

              

        Application application = new Application();

        application.setVisible(true);

        //restante do método

//restante da classe

Listagem 01

 

Como visto no código acima, Application é a classe responsável pela interface gráfica e pode ser qualquer JPanel, JFrame, com quaisquer componentes. Como o objetivo do artigo é focar os look-and-feels não se entrará muito em detalhes nem será visto o código da aplicação.

 

O que interessa aqui é a chamada a setLookAndFeel de UIManager, que possui métodos static para manuseio das look-and-feels.

 

Primeiramente, é obtida uma String representando o look-and-feel do sistema operacional ativo. Para o exemplo deste artigo será utilizado o Windows XP, logo, a string retornada por UIManager.getSystemLookAndFeelClassName será: com.sun.java.swing.plaf.windows.WindowsLookAndFeel.

 

Em seguida, essa string é passada para o UIManager através de setLookAndFeel, dentro de um bloco try – necessário, pois o mesmo lança uma série de exceções que não serão descritas aqui.

 

Após essa chamada, antes da interface ser lançada na tela, o java renderizará qualquer componente gráfico de acordo com as características visuais do Windows XP (para o exemplo atual). A figura 1 representa uma janela visualizada sem nenhuma alteração de look-and-feel e ao lado a gerada de acordo com o código da listagem 1.

 

asplascsfig01.jpg 

Figura 1

 

Visualizando diferentes tipos de Look-and-feel

Na seção anterior, foi demonstrado como alterar o look-and-feel de uma aplicação já pronta sem necessidade de alterar seu código. O que será feito agora é uma interface gráfica simples para que o leitor possa ver diferentes tipos em tempo de execução.

 

A listagem 2 representa um frame simples contendo esta funcionalidade.

 

//imports aqui...

public class LookAndFeels extends JFrame implements ActionListener{

       

        JTextArea textArea = new JTextArea("\n\n\n\n\n\n\n\n\n\n\n\n\n", 8, 10);

        JScrollPane jScrollPane = new JScrollPane(textArea);

        UIManager.LookAndFeelInfo lafs[] = UIManager.getInstalledLookAndFeels();

       

        public LookAndFeels(){

               super.setLayout(new FlowLayout());

               add(new JLabel("Testando Look-and-feels..."));

               for (int i = 0; i < lafs.length; i++) {

                       JButton button = new JButton(lafs[i].getClassName());

                       button.addActionListener(this);

                       add(button);

               }

               add(jScrollPane);

              

               super.setSize(450, 290);

        }

       

        public void actionPerformed(ActionEvent event){

               JButton buttonClassName = (JButton)event.getSource();

               String lookAndFeel = buttonClassName.getText();

               changeLookAndFeel(lookAndFeel);

        }

       

        public void changeLookAndFeel(String lookAndFeel){

               try{

                       UIManager.setLookAndFeel(lookAndFeel);

                       SwingUtilities.updateComponentTreeUI(this);

               } catch(Exception e){e.printStackTrace();}

        }

       

        public static void main(String[] args) {

               LookAndFeels feels = new LookAndFeels();

               feels.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

               feels.setVisible(true);

        }

}

Listagem 02

 

JTextArea é inicializada com o valor "\n\n\n\n\n\n\n\n\n\n\n\n\n" para que o usuário não precise teclar “enters” para visualizar a barra de rolagem ativa. Em seguida o JScrollPane é criado pra adicionar essa barra de rolagem.

 

UIManager.getInstalledLookAndFeels retorna um array contendo todos os look-and-feels instalados, que são armazenados em lafs[] e utilizados posteriormente para criar um JButton para cada um deles.

 

O método actionPerformed é uma implementação necessária pelo fato da classe implementar ActionListener e é responsável por armazenar a string que é o nome da classe referente ao look-and-feel escolhido pelo usuário. Em seguida o método changeLookAndFeel é chamado passando essa string.

 

Este método realiza uma ação parecida com a da seção anterior, porém com uma diferença, ele chama SwingUtilities.updateComponentTreeUI para que os componentes sejam novamente renderizados. Sem essa chamada não há alterações bem sucedidas e alguns itens possuem apenas parte de seus componentes gráficos renderizados.

 

Após executar a aplicação o usuário poderá escolher qual look-and-feel deseja visualizar e alterar em tempo de execução para comparar seus componentes e tamanhos, visto que em alguns casos será necessário redimensionar e reposicioná-los devidas as diferenças de dimensões entre look-and-feels distintos.

 

Como funciona a alteração de um look-and-feel

Será brevemente descrito agora como o java trabalha no momento da alteração, em tempo de execução, de um look-and-feel.

 

Todos componentes que herdam JComponent possuem um método chamado updateUI. SwingUtilities.updateComponentTreeUI é apenas uma maneira de fazer com que todos os elementos presentes na interface gráfica tenham seus métodos updateUI invocados recursivamente. Em geral, as implementações de updateUI fazem referências a chamadas a UIDefaults.getUI.

 

Tendo então as informações presentes na look-and-feel instalada, uma instância de UI é criada de acordo com as necessidades do componente atual (no momento da recursão realizada em SwingUtilities.updateComponentTreeUI.

 

Essa instância geralmente fornece as informações referentes à interface do usuário necessárias ao java para completa renderização dos componentes, porém, sem alterar propriedades fundamentais que poderiam interferir na execução da aplicação. Isso permite que uma look-and-feel seja alterada em tempo de execução com segurança (sem contar o fato delas não terem dimensões que correspondam ao design gráfico adotado).

 

Conclusão

É fato que a disponibilização de look-and-feels pelo Java foi de grande importância para a comunidade de programadores e empresas de desenvolvimento, pois permite criar aplicações que se assemelham e comportam-se como se fossem do sistema operacional vigente, por exemplo.

 

Existem diversos look-and-feels disponíveis para download na internet, alguns deles gratuitos. E se nenhum deles agrada ou seja de vontade do desenvolvedor é possível customizar um!

 

Um grande abraço e até a próxima!

Adriano Castro