Java First-Tier: Aplicações Construção de Interfaces com Swing Swing versus AWT Conjunto maior de elementos Maior consistência de uso entre plataformas Pacote javax.swing Pacote de extensão no Java 1.1 Incorporado como pacote básico no Java 2 2 Swing: Características Componentes leves Diagramadores & Listeners do AWT Look & Feel configurável Arquitetura MVC 3 Arquitetura MVC O Swing adota uma arquitetura conhecida como Model-View-Controller (MVC) – Modelo = dados – Visão = aparência – Controle = comportamento 4 Hierarquia de Classes Object Component Container Window Frame JFrame JComponent JLabel JAbstractButton JButton JToggleButton ... 5 Classe JFrame Modela uma janela do sistema nativo Equivalente, no Swing, à classe Frame do AWT 6 Estrutura de um JFrame © The Java TM Tutorial 7 JRootPane A lightweight container used behind the scenes by JFrame, JDialog, JWindow, JApplet, and JInternalFrame. For task-oriented information on functionality provided by root panes see How to Use Root Panes, a section in The Java Tutorial. The following image shows the relationships between the classes that use root panes. 8 9 The "heavyweight" components (those that delegate to a peer, or native component on the host system) are shown with a darker, heavier box. The four heavyweight JFC/Swing containers (JFrame, JDialog, JWindow, and JApplet) are shown in relation to the AWT classes they extend. These four components are the only heavyweight containers in the Swing library. The lightweight container JInternalPane is also shown. All five of these JFC/Swing containers implement the RootPaneContainer interface, and they all delegate their operations to a JRootPane (shown with a little "handle" on top). Note: The JComponent method getRootPane can be used to obtain the JRootPane that contains a given component. The diagram at right shows the structure of a JRootPane. A JRootpane is made up of a glassPane, an optional menuBar, and a contentPane. (The JLayeredPane manages the menuBar and the contentPane.) The glassPane sits over the top of everything, where it is in a position to intercept mouse movements. Since the glassPane (like the contentPane) can be an arbitrary component, it is also possible to set up the glassPane for drawing. Lines and images on the glassPane can then range over the frames underneath without being limited by their boundaries. 10 Although the menuBar component is optional, the layeredPane, contentPane, and glassPane always exist. Attempting to set them to null generates an exception. To add components to the JRootPane (other than the optional menu bar), you add the object to the contentPane of the JRootPane, like this: rootPane.getContentPane().add(child); 11 The same principle holds true for setting layout managers, removing components, listing children, etc. All these methods are invoked on the contentPane instead of on the JRootPane. Note: The default layout manager for the contentPane is a BorderLayout manager. However, the JRootPane uses a custom LayoutManager. So, when you want to change the layout manager for the components you added to a JRootPane, be sure to use code like this: rootPane.getContentPane().setLayout(new BoxLayout()); If a JMenuBar component is set on the JRootPane, it is positioned along the upper edge of the frame. The contentPane is adjusted in location and size to fill the remaining area. (The JMenuBar and the contentPane are added to the layeredPane component at the JLayeredPane.FRAME_CONTENT_LAYER layer.) The layeredPane is the parent of all children in the JRootPane -- both as the direct parent of the menu and the grandparent of all components added to the contentPane. It is an instance of JLayeredPane, which provides the ability to add components at several layers. This capability is very useful when working with menu popups, dialog boxes, and dragging -- situations in which you need to place a component on top of all other components in the pane. The glassPane sits on top of all other components in the JRootPane. That provides a convenient place to draw above all other components, and makes it possible to intercept mouse events, which is useful both for dragging and for drawing. Developers can use setVisible on the glassPane to control when the glassPane displays over the other children. By default the glassPane is not visible. 12 13 Main differences in use compared to Frame: Components go in the "content pane", not directly in the frame. Changing other properties (layout manager, background color, etc.) also apply to the content pane. Access content pane via getContentPane, or if you want to replace the content pane with your container (e.g. a JPanel), use setContentPane. JFrames close automatically when you click on the close button (unlike AWT Frames). However, closing the last JFrame does not result in your program exiting Java. So your "main" JFrame still needs a WindowListener. You get Java (Metal) look by default, so you have to explicitly switch if you want native look. 14 Métodos de JFrame JRootPane getRootPane() Container getContentPane() void setJMenuBar(JMenuBar menubar) JMenuBar getJMenuBar() void setDefaultCloseOperation(int op) – DO_NOTHING_ON_CLOSE – HIDE_ON_CLOSE – DISPOSE_ON_CLOSE – EXIT_ON_CLOSE 15 Exemplo de JFrame JFrame f = new JFrame("Teste"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); f.show(); 16 Classe JComponent Superclasse de muitos elementos do Swing, disponibiliza métodos para controlar: – Tool tips – Bordas – Propriedades 17 Métodos de JComponent void setToolTipText(String text) String getToolTipText() void setBorder(Border border) Border getBorder() final void putClientProperty(Object key, Object value) final Object getClientProperty(Object key) 18 Classe JLabel Essa classe modela um texto e/ou imagem não editável, isto é, sem interação com o usuário É o equivalente, no Swing, ao Label do AWT, só que com mais recursos Pode-se controlar tanto o alinhamento horizontal como o vertical, e o JLabel pode passar o foco para outro elemento 19 Métodos de JLabel void setText(String text) void setIcon(Icon icon) void setIconTextGap(int gap) void setHorizontalAlignment(int a) void setVerticalAlignment(int a) void setLabelFor(Component c) void setDisplayedMnemonic(int key) void setDisplayedMnemonic(char aChar) 20 Exemplo de JLabel JFrame f = new JFrame("Teste"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JLabel l = new JLabel("Isso é um JLabel"); l.setIcon(new ImageIcon("javalogo.gif")); Container cp = f.getContentPane(); cp.add(l); f.pack(); f.show(); 21 Classe JButton Modela um push-button Sendo uma sub-classe de AbstractButton, herda os métodos getLabel e setLabel que permitem consultar e alterar seu texto 22 Métodos de JButton JButton(String text) JButton(String text, Icon icon) void setLabel(String label) String getLabel() 23 Exemplo de JButton JFrame f = new JFrame("Teste"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JButton b1 = new JButton("Botão 1"); JButton b2 = new JButton("Botão 2"); Container cp = f.getContentPane(); cp.setLayout(new GridLayout(1,0)); cp.add(b1); cp.add(b2); f.pack(); f.show(); 24 Classe JRadioButton Modela um botão de escolha que pode ser marcado e desmarcado Objetos do tipo JRadioButton são organizados em grupos Apenas um único botão de um grupo pode estar marcado em um dado momento 25 Métodos de JRadioButton JRadioButton(String label) JRadioButton(String label, boolean state) boolean isSelected() void setSelected(boolean state) 26 Classe ButtonGroup Cria um “escopo” de exclusão para um grupo de botões Basta criar um ButtonGroup e adicionar a ele os JRadioButtons que compõem o grupo 27 Métodos de ButtonGroup void add(AbstractButton b) ButtonModel getSelection() boolean isSelected(ButtonModel m) void setSelected(ButtonModel m, boolean state) 28 Classe JCheckBox Modela um botão de escolha que pode ser marcado e desmarcado 29 Métodos de JCheckBox public JCheckBox(String label) public JCheckBox(String label, boolean state) public boolean isSelected() public void setSelected(boolean state) 30 Classe JTextComponent Classe abstrata que modela o que há de comum entre diferentes elementos de edição de texto public void setText(String t) public String getText() public void setEditable(boolean b) 31 Elementos de Edição de Texto JEditorPane JTextArea JTextPane © The Java TM Tutorial 32 Classe JTextField Cria um campo de edição de texto de uma linha JTextField() JTextField(String text) JTextField(int columns) JTextField(String text, int columns) void setColumns(int columns) 33 Classe JPasswordField Estende JTextField Caracteres digitados não são exibidos JPasswordField() JPasswordField(int columns) JPasswordField(String text, int columns) char[] getPassword() void setEchoChar(char c) 34 Classe JTextArea Cria um campo de edição de texto com múltiplas linhas JTextArea(int rows, int columns) JTextArea(String text, int rows, int columns) void append(String t) void insert(String t, int pos) void setLineWrap(boolean wrap) void setWrapStyleWord(boolean word) 35 Classe JTextPane Componente de texto que suporta atributos representados graficamente (styled text) Permite o uso de diversas “fontes” no texto Permite a inclusão de imagens e de outros componentes 36 Classe JPanel Modela um container sem decoração, normalmente utilizado para estruturar a interface Equivalente, no Swing, à classe Panel do AWT 37 Métodos de JPanel JPanel() JPanel(LayoutManager mgr) void setLayout(LayoutManager mgr) Component add(Component comp) void add(Component c, Object constraints) 38 Exemplo de JPanel JFrame f = new JFrame("Teste"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JButton b1 = new JButton("Botão 1"); JButton b2 = new JButton("Botão 2"); JPanel p = new JPanel(); p.add(b1); p.add(b2); f.getContentPane().add(p); f.pack(); f.show(); 39 Exemplos de Bordas © The Java TM Tutorial 40 Mais exemplos... © The Java TM Tutorial 41 BorderFactory Contém métodos para a criação de diferentes tipos de bordas static static static static Border createLineBorder(Color color) Border createEtchedBorder() TitledBorder createTitledBorder(String t) TitledBorder createTitledBorder(Border b, String t) 42 Painéis, Bordas e Botões JCheckBox JRadioButton 43 Classe JList Modela um elemento que apresenta uma lista de opções ao usuário Permite a seleção simples (um único elemento), ou múltipla (vários elementos) 44 Métodos de JList JList(Object[] listData) void setSelectionMode(int selectionMode) int getSelectedIndex() int[] getSelectedIndices() Object getSelectedValue() Object[] getSelectedValues() 45 Exemplo de JList JFrame f = new JFrame("Teste"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String[] nomes = {"a", "b", "c", "d", "e", "f"}; JList l = new JList(nomes); Container cp = f.getContentPane(); cp.add(l); f.pack(); f.show(); 46 Barras de Rolagem No Swing, ao invés de repetir o código que implementa o uso de barras de rolagem (scrollbars) em diferentes elementos, foi criado um elemento de interface cujo único objetivo é fornecer essa funcionalidade A classe JScrollPane modela esse elemento e a interface Scrollable define o que cada elemento deve ter para poder ser tratado por um JScrollPane 47 Elementos Scrollable As classes JList, JTextComponent, JTree e JTable implementam a interface Scrollable e, portanto, suas instâncias podem ser usadas com JScrollPane 48 Exemplo: JScrollPane com JList JFrame f = new JFrame("Teste"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String[] nomes = {"a", "b", "c", "d", "e", "f"}; JList l = new JList(nomes); JScrollPane sp = new JScrollPane(l); Container cp = f.getContentPane(); cp.add(sp); f.pack(); f.show(); 49 Explorando a Arquitetura MVC Como os dados (o modelo) não fazem parte integrante do elemento de interface que os exibe, podemos gerenciá-los em separado Por exemplo, é possível exibir um mesmo conjunto de dados em mais de um elemento de interface, simultaneamente Também é possível fazer com que o elemento de interface use os dados originais, sem copiá-los 50 Exemplo de Uso Suponha que você tem uma lista de nomes muito grande e deseja exibí-la em uma JList Usando a forma que vimos, esses nomes seriam copiados para dentro da lista Para evitar essa replicação, podemos utilizar um modelo próprio, que permitirá à JList acessar diretamente a lista de nomes 51 Interface ListModel Define o modelo usado pela classe JList Abrange dois aspectos: 1. o acesso aos dados 2. o controle da modificação dos dados 52 Métodos de ListModel int getSize() Object getElementAt(int index) void addListDataListener( ListDataListener l) void removeListDataListener( ListDataListener l) 53 De Volta ao Exemplo Imagine que os nomes estão armazenados em um array de String Assumindo que a lista de nomes não é modificada, podemos ignorar o listener Basta, então, definir uma classe que implemente ListModel e utilize o array como fonte dos dados 54 Criando um Modelo class ListaDeNomes implements ListModel { private String[] nomes; ListaDeNomes(String[] nomes) { this.nomes = nomes; } public int getSize() { return nomes.length; } public Object getElementAt(int index) { return nomes[index]; } public void addListDataListener(ListDataListener l) {} public void removeListDataListener(ListDataListener l) {} } 55 Usando o Modelo JFrame f = new JFrame("Teste"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String[] nomes = {"a", "b", "c", "d", "e", "f"}; JList l = new JList(new ListaDeNomes(nomes)); Container cp = f.getContentPane(); cp.add(new JScrollPane(l)); f.pack(); f.show(); 56 Classe JOptionPane Métodos estáticos para a criação desses diálogos simples Estrutura básica: mensagem ícone entrada de dados botões de opção 57 MessageDialog Exibe uma mensagem e aguarda OK do usuário INFORMATION QUESTION WARNING ERROR PLAIN 58 Método showMessageDialog void showMessageDialog(Component parentComponent, Object message); void showMessageDialog(Component parentComponent, Object message, String title, int messageType); void showMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon); 59 Exemplo de MessageDialog JOptionPane.showMessageDialog(janela, "Cuidado com o apagão!", "ATENÇÃO", JOptionPane.WARNING_MESSAGE); 60 ConfirmDialog Exibe uma mensagem e obtém uma confirmação (YES/NO, OK/CANCEL) Conjuntos de botões de opção (optionType): – JOptionPane.DEFAULT_OPTION – JOptionPane.YES_NO_OPTION – JOptionPane.YES_NO_CANCEL_OPTION – JOptionPane.OK_CANCEL_OPTION 61 Método showConfirmDialog int showConfirmDialog(Component parentComponent, Object message); int showConfirmDialog(Component parentComponent, Object message, String title, int optionType); int showConfirmDialog(Component parentComponent, Object message, String title, int optionType int messageType, Icon icon); 62 Exemplo de ConfirmDialog int resp = JOptionPane.showConfirmDialog(janela, "Prossegue com a tarefa?", "Escolha uma opção", JOptionPane.OK_CANCEL_OPTION); CLOSED_OPTION OK_OPTION CANCEL_OPTION 63 InputDialog Exibe uma mensagem e obtém um valor de entrada do usuário – campo de texto editável – combo box 64 Método showInputDialog String showInputDialog(Component parentComponent, Object message); String showInputDialog(Component parentComponent, Object message, String title, int messageType); Object showInputDialog(Component parentComponent, Object message, String title, int messageType Icon icon, Object[] selectionValues, Object defaultSelection); 65 Exemplo de InputDialog String nome = JOptionPane.showInputDialog(janela, "Qual é o seu nome?", "Identifique-se", JOptionPane.QUESTION_MESSAGE); 66 OptionDialog Exibe uma mensagem (ou objeto) e obtém uma opção escolhida pelo usuário O número de botões e seus textos são configuráveis A opção default é configurável 67 Método showOptionDialog int showOptionDialog(Component parentComponent, Object message, String title, int optionType int messageType, Icon icon, Object[] options, Object initialValue); 68 Exemplo de OptionDialog Object[] opções = {"Sim", "Não", "Mais Tarde", "Amanhã", "Sei lá!"}; int resp = JOptionPane.showOptionDialog(janela, "Prossegue com a tarefa?", "Escolha uma opção", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, opções, opções[0]); 69 Exemplo de OptionDialog 70 Classe JFileChooser É comum uma aplicação abrir e salvar arquivos A classe JFileChooser implementa uma caixa de diálogo que permite que o usuário navegue pelo sistema de arquivos – semelhante às usadas por aplicações “nativas” 71 Diálogo de Seleção de Arquivos 72 Métodos de JFileChooser void void void void setCurrentDirectory(File dir) setSelectedFile(File file) setMultiSelectionEnabled(boolean b) setFileFilter(FileFilter filter) int showOpenDialog(Component parent) int showSaveDialog(Component parent) int showDialog(Component parent, String approveButtonText) File getSelectedFile() File[] getSelectedFiles() 73 Exemplo de JFileChooser JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(new File("c:\\jdk1.3")); int res = chooser.showOpenDialog(janela); if (res == JFileChooser.APPROVE_OPTION) { File file = chooser.getSelectedFile(); System.out.println(file.getName()); } 74 Gerenciadores de Layout A layout manager is an object that implements the LayoutManager interface* and determines the size and position of the components within a container. Although components can provide size and alignment hints, a container's layout manager has the final say on the size and position of the components within the container. 75 Gerenciadores de Layout Setting the Layout Manager As a rule, the only containers whose layout managers you need to worry about are JPanels and content panes . Each JPanel object is initialized to use a FlowLayout, unless you specify differently when creating the JPanel. Content panes use BorderLayout by default. If you don't like the default layout manager that a panel or content pane uses, you're free to change it to a different one. You can set a panel's layout manager using the JPanel constructor. For example: JPanel panel = new JPanel(new BorderLayout()); After a container has been created, you can set its layout manager using the setLayout method. For example: Container contentPane = frame.getContentPane(); contentPane.setLayout(new FlowLayout()); Although we recommend that you use layout managers, you can perform layout without them. By setting a container's layout property to null, you make the container use no layout manager. With this strategy, called absolute positioning, you must specify the size and position of every component within that container. One drawback of absolute positioning is that it doesn't adjust well when the top-level container is resized. It also doesn't adjust well to differences between users and systems, such as different font sizes and locales . 76 Adding Components to a Container When you add components to a panel or content pane, the arguments you specify to the add method depend on the layout manager that the panel or content pane is using. For example, BorderLayout requires that you specify the area to which the component should be added, using code like this: pane.add(aComponent, BorderLayout.PAGE_START); The how-to section for each layout manager has details on what, if any, arguments you need to specify to the add method. Some layout managers, such as GridBagLayout and SpringLayout, require elaborate setup procedures. Many layout managers, however, simply place components based on the order they were added to their container. Swing containers other than JPanel and content panes generally provide API that you should use instead of the add method. For example, instead of adding a component directly to a scroll pane (or, actually, to its viewport), you either specify the component in the JScrollPane constructor or use setViewportView. Because of specialized API like this, you don't need to know which layout manager (if any) many Swing containers use. (For the curious: scroll panes happen to use a layout manager named ScrollPaneLayout.) For information about how to add components to a specific container, see the how-to page for the container. You can find the component how-to pages using A Visual Index to the Swing Components . 77 Providing Size and Alignment Hints Sometimes you need to customize the size hints that a component provides to its container's layout manager, so that the component will be laid out well. You can do this by specifying one or more of the minimum, preferred, and maximum sizes of the component. You can invoke the component's methods for setting size hints — setMinimumSize, setPreferredSize, and setMaximumSize. Or you can create a subclass of the component that overrides the appropriate getter methods — getMinimumSize, getPreferredSize, and getMaximumSize. Here is an example of making a component's maximum size unlimited: component.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); Many layout managers don't pay attention to a component's requested maximum size. However, BoxLayout and SpringLayout do. Besides providing size hints, you can also provide alignment hints. For example, you can specify that the top edges of two components should be aligned. You set alignment hints either by invoking the component's setAlignmentX and setAlignmentY methods, or by overriding the component's getAlignmentX and getAlignmentY methods. Although most layout managers ignore alignment hints, BoxLayout honors them. You can find examples of setting the alignment in How to Use BoxLayout. 78