Vamos discutir como construir aplicações com interface gráfica de usuário (conhecida como GUI - Graphical User Interface). Numa interface gráfica existem botões, caixas de texto, painéis, barras de rolagem, e muitos outros componentes com os quais o usuário pode interagir. As primeiras versões da linguagem Java disponibilizavam o pacote AWT (Abstract Window Toolkit) para a construção de GUIs. Sistemas desenvolvidos com AWT são dependentes da plataforma, ou seja, em plataformas diferentes as interfaces gráficas podem ser exibidas de forma diferente, pois AWT usa as primitivas gráficas de cada plataforma. Atualmente, a linguagem Java disponibiliza o pacote Swing para a construção de GUIs. Com Swing, os programas não são dependentes de plataforma. O pacote Swing oferece uma biblioteca bastante extensa de componentes para o desenvolvimento de GUIs que executam em qualquer plataforma com a mesma aparência (Look & Feel). ELFS 183
Interfaces Gráficas em Java Em Java, os programas com interface gráfica de usuário podem ser desenvolvidos de duas maneiras: Programas que são executados utilizando o ambiente gráfico de um navegador web. Estes programas são conhecidos como applets. Sistemas desktop que são executadas diretamente em uma determinada plataforma. As duas maneiras seguem o mesmo princípio: construir a interface gráfica a partir de um contexto gráfico e, em seguida, capturar e tratar os eventos gerados pelos componentes da GUI devido à interação com o usuário. A estrutura de pacotes disponível é a mesma: java.lang.object java.awt.component java.awt.container javax.swing.jcomponent ELFS 184
Toda interface gráfica em Java tem como superclasse de mais alto nível a classe java.awt.component. Logo, qualquer objeto presente em uma janela gráfica é um Component. Basicamente há dois tipos de componentes: descendentes diretos de Component (CheckBox, Button, Label,...) e descendentes de Container (Panel, Window,...). Os principais métodos de Component são: paint, repaint e update. Os métodos paint e update recebem um objeto da classe java.awt.graphics2d como parâmetro (o que deve ser desenhado). ELFS 185
Os descendentes de java.awt.container são componentes que podem conter outros componentes como Panel, ScrollPane, Window e JComponent que é a classe raiz de todos os componentes Swing. JComponent Neste curso, vamos nos concentrar nos componentes Swing. ELFS 186
Toda aplicação Swing requer, pelo menos, um container para acomodar os demais componentes que irão compor a GUI. As classes dos containers possuem métodos apropriados para o desenho de componentes e para o tratamento dos eventos gerados devido à interação do usuário. As principais classes containers Swing são: JApplet: Um painel (subclasse de java.awt.panel) que serve de base para as aplicações executadas a partir de um navegador web. JFrame: Implementa uma janela gráfica com todas as funcionalidades (redimensionamento, fechamento, minimização,...) sendo, portanto, a classe base para qualquer aplicativo com GUI. JDialog: Implementa uma janela gráfica dependente de outra janela. Uma aplicação Swing deve corresponder a uma subclasse de uma dessas classes container. O posicionamento dos elementos no container é feito de maneira automática pelos diversos gerenciadores de layout disponíveis. Cada container tem seu gerenciador de layout padrão. Se não existir um gerenciador de layout associado ao container (layout = null), o posicionamento dos componentes no container deve ser feito manualmente. ELFS 187
Componentes Swing similares aos encontrados no pacote AWT. A diferença é feita pela letra J colocada antes do nome do componente AWT. AbstractButton JButton JMenuItem JCheckBoxMenuItem JMenu JRadioButtonMenuItem JComboBox JToggleButton JCheckBox JRadioButton JLabel JList JComponent JMenuBar JPanel JPopupMenu JScrollBar JScrollPane JEditorPane JTextPane JTextComponent JTextArea JTextField JPasswordField ELFS 188
Componentes Swing que não existem no pacote AWT. JColorChooser JFileChooser JInternalFrame JLayeredPane JDesktopPane JComponent JOptionPane JProgressBar JRootPane JSeparator JSlider JSplitPane JTabbedPane JTable JToolBar JToolTip JTree JViewPort JPopupMenuSeparator JToolBarSeparator JInternalFrameDesktopIcon ELFS 189
Exemplo 1: Uma janela sem nada Programas Java com GUI podem ser criados a partir da classe JFrame, que é o principal container para uma aplicação Swing. import javax.swing.*; Exemplo1.java public class Exemplo1 extends JFrame public Exemplo1() // Define o título da janela super("primeira Janela"); this.setsize(320,240); this.setvisible(true); Os métodos setsize() e setvisible() são obrigatórios. Comente essa linha e verifique o que acontece. public static void main(string[] args) Exemplo1 janela = new Exemplo1(); Os parâmetros de inicialização da janela, como o título (através da chamada do construtor de JFrame) e o tamanho devem ser definidos no construtor padrão da aplicação. O que acontece ao fechar a janela? ELFS 190
Exemplo 2: Liberar a JVM ao fechar a janela import javax.swing.*; import java.awt.event.*; Exemplo2.java public class Exemplo2 extends JFrame public Exemplo2() // Define o título da janela super("primeira Janela"); this.setsize(320,240); this.setvisible(true); public static void main(string[] args) Exemplo2 janela = new Exemplo2(); janela.addwindowlistener( new WindowAdapter() public void windowclosing( WindowEvent e ) System.exit( 0 ); ); Normalmente, quando uma janela é fechada ela apenas se torna invisível. Com esses comandos, ao fechar a janela será chamado o método exit(), que libera a JVM. ELFS 191
Exemplo 3: Adicionando componentes import java.awt.*; import javax.swing.*; import java.awt.event.*; Exemplo3.java public class Exemplo3 extends JFrame public Exemplo3() JFrame frame = new JFrame("Janela com elementos"); frame.setdefaultcloseoperation(jframe.exit_on_close); JLabel label = new JLabel("Elemento Label"); JButton botao = new JButton("Botão Simples"); Container c = frame.getcontentpane(); c.add(botao); c.add(label); // c.setlayout(new FlowLayout()); frame.setsize(320,240); frame.setvisible(true); public static void main(string[] args) Exemplo3 janela = new Exemplo3(); janela.addwindowlistener(new WindowAdapter() public void windowclosing( WindowEvent e ) System.exit( 0 ); ); Os componentes são apresentados na área de conteúdo (ContentPane) do JFrame. Porque somente um componente é visível? Por causa do gerenciador de layout! Retire o comentário da linha c.setlayout() e observe o que acontece. ELFS 192
O Componente JPanel Interfaces gráficas complexas exigem componentes colocados em posições específicas. A interface gráfica da aplicação a seguir, por exemplo, pode ser construída usando-se 4 painéis: superior (P1), inferior (P2), à esquerda (P3) e à direita (P4). P1 P3 P4 P2 Um painel é um contêiner e portanto, pode conter qualquer outro componente, inclusive outros painéis. Cada painel pode ter o seu próprio gerenciador de layout. Assim, pode-se construir interfaces gráficas bastante sofisticadas. ELFS 193
Exemplo 4: Janela usando painéis import java.awt.*; import javax.swing.*; import java.awt.event.*; Exemplo4.java public class Exemplo4 extends JFrame public Exemplo4() JFrame frame = new JFrame("Janela usando painéis"); JPanel p1 = new JPanel(); JPanel p2 = new JPanel(); JPanel p3 = new JPanel(); JLabel label = new JLabel("Elemento JLabel"); JButton botao = new JButton("Botão simples"); JButton outro = new JButton("Outro botão"); frame.setsize(320,240); p1.setbackground(color.yellow); Cor de fundo do painel. p2.setbackground(color.white); p1.add(label); p2.add(botao); p3.add(outro); Container c = frame.getcontentpane(); c.setlayout(new BorderLayout()); c.add(p1,borderlayout.north); c.add(p2,borderlayout.south); c.add(p3,borderlayout.east); frame.setvisible(true); Adicionar o método main() O gerenciador BorderLayout divide o painel de conteúdo em 5 regiões: norte, sul, leste, oeste e centro. semelhante ao do exemplo anterior. ELFS 194
Gerenciadores de Layout Os gerenciadores de layout organizam os componentes GUI em um contêiner para fins de apresentação. São estes gerenciadores que, a priori, definem o posicionamento e o tamanho dos componentes em um contêiner. Alguns componentes têm métodos para definir ou recuperar o tamanho preferencial: setpreferredsize(): existe para alguns componentes para os quais é possível definir o tamanho ideal. getpreferredsize(): existe para todos os componentes, podendo ser sobreposto em subclasses do componente. É chamado pelos gerenciadores que o respeitam: FlowLayout e BorderLayout. Se o gerenciador de layout for desligado, com setlayout(null), será necessário posicionar cada um dos componentes manualmente, com o método: componente.setbounds(x, y, largura, altura). Os principais gerenciadores de layout são: FlowLayout BorderLayout GridLayout SpringLayout ELFS 195
FlowLayout Padrão para JPanel. Coloca os componentes seqüencialmente em linha (da esquerda para a direita) na ordem em que são adicionados. Se eles não couberem na largura da janela uma nova linha é iniciada. É possível especificar a ordem dos componentes com o método: public Component add(component comp, int index) Permite que os componentes GUI sejam alinhados à esquerda, centralizados (o padrão) ou alinhados à direita. O PreferredSize é respeitado para todos os componentes. BorderLayout Padrão para JFrame, JDialog e JApplet. Organiza os componentes em 5 regiões: Norte, Sul, Leste, Oeste e Centro. Todo o espaço não utilizado pelos extremos é deixado para o centro. Cada uma das regiões só aceita um componente. No caso de haver vários componentes, adicionar um JPanel e depois adicionar os componentes ao painel. NORTH e SOUTH têm prioridade na ocupação da largura, mas são limitadas na altura pelo PreferredSize dos componentes. EAST e WEST tem altura limitada pela existência ou não de NORTH e SOUTH e largura limitada pelo PreferredSize dos componentes. CENTER ocupa todo o espaço restante. ELFS 196
GridLayout Organiza os componentes em linhas e colunas, da esquerda para a direita e de cima para baixo. Se houver mais células que componentes as últimas células ficarão vazias. Qualquer componente adicionado a uma célula ocupa toda a célula. Quando a janela é redimensionada, todos os componentes também são redimensionados. O gerenciador não respeita o PreferredSize dos componentes. SpringLayout Gerenciador de layout flexível, normalmente utilizado por construtores automáticos de GUI. Permite que se especifique as distâncias que devem existir entre os componentes controlados pelo gerenciador. Pode-se, por exemplo, definir a distância que deve existir entre o vértice superior esquerdo de um componente e o vértice inferior direito de outro. Esta distância pode ser calculada dinamicamente. ELFS 197
Exemplo 5: Uso do gerenciador FlowLayout import java.awt.*; import javax.swing.*; import java.awt.event.*; Exemplo5.java public class Exemplo5 extends JFrame public Exemplo5() JFrame frame = new JFrame("Frame com FlowLayout"); JButton b1 = new JButton("Botão 1"); JButton b2 = new JButton("Botão 2"); JButton b3 = new JButton("Botão 3"); frame.setsize(320,120); Container c = frame.getcontentpane(); c.add(b1); c.add(b2); c.add(b3); c.setlayout(new FlowLayout(FlowLayout.RIGHT)); frame.setvisible(true);... Não esquecer de acrescentar aqui, o método main() semelhante ao do exemplo anterior. ELFS 198
Exemplo 6: Uso do gerenciador BorderLayout import java.awt.*; import javax.swing.*; import java.awt.event.*; Exemplo6.java public class Exemplo6 extends JFrame public Exemplo6() JFrame frame = new JFrame("Frame com BorderLayout"); JButton b1 = new JButton("Botão 1"); JButton b2 = new JButton("Botão 2"); JButton b3 = new JButton("Botão 3"); JButton b4 = new JButton("Botão 4"); JButton b5 = new JButton("Botão 5"); frame.setsize(320,240); Container c = frame.getcontentpane(); c.add(b1, BorderLayout.NORTH); c.add(b2, BorderLayout.SOUTH); c.add(b3, BorderLayout.EAST); c.add(b4, BorderLayout.WEST); c.add(b5, BorderLayout.CENTER); frame.setvisible(true);... Não esquecer de acrescentar o método main(). ELFS 199
Exemplo 7: Uso do gerenciador GridLayout import java.awt.*; import javax.swing.*; import java.awt.event.*; Exemplo7.java public class Exemplo7 extends JFrame public Exemplo7() JFrame frame = new JFrame("Frame com GridLayout"); frame.setdefaultcloseoperation(jframe.dispose_on_close); JButton b1 = new JButton("Botão 1");... JButton b2 = new JButton("Botão 2"); JButton b3 = new JButton("Botão 3"); JButton b4 = new JButton("Botão 4"); frame.setsize(320,160); Container c = frame.getcontentpane(); c.setlayout(new GridLayout(2,2)); c.add(b1); c.add(b2); c.add(b3); c.add(b4); frame.setvisible(true); Não esquecer de acrescentar o método main(). Liberar a memória (destruir) ao fechar a janela. ELFS 200
Exercícios: Criar as seguintes GUIs (não é necessário fornecer funcionalidade alguma): ELFS 201