Buscar

Aula 4 - Interfaces grácas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 33 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 33 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 33 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Interfaces de BD 
Aula 4: Interfaces grá�cas 
Apresentação
Computadores pessoais evoluíram muito desde as primeiras versões, e com esta evolução, as antigas interfaces de linha
de comando não eram su�cientes para prover o nível de resposta necessário para o usuário padrão, o que levou à
popularização das interfaces grá�cas, com a representação e utilização dos recursos de sistema de forma muito mais
intuitiva. 
Na linguagem Java, é possível implementar uma interface grá�ca, ou GUI, com o uso de diversas opções de bibliotecas,
cada uma delas com características especí�cas, mas mantendo alguns princípios globais e padrões reconhecidos e
aceitos. 
Além de criar um ambiente de maior usabilidade, com a adoção de bibliotecas para a construção de GUI, devemos pensar
em termos de armazenagem de dados, já que o usuário precisa das informações que foram geradas em execuções
anteriores do sistema, e a combinação de GUI com meios de persistência permitirá a criação de sistemas cadastrais com
aplicabilidade real. 
Objetivos
Explicar o funcionamento de interfaces grá�cas no Java; 
Usar eventos para interação com o usuário; 
Examinar a persistência de dados baseada em arquivos. 
Graphical User Interface (GUI) 
As interfaces grá�cas são comuns atualmente e se tornaram um elemento obrigatório para qualquer sistema operacional
voltado para o usuário, mas nem sempre foi assim. Os primeiros sistemas utilizados em computadores pessoais trabalhavam
em modo texto, envolvendo entrada apenas através do teclado e saída em modo texto, com caracteres ASCII, para o vídeo, da
mesma forma que os terminais de mainframes. 
Os computadores pessoais evoluíram, e as interfaces de usuário, que eram apenas emissores de caracteres em preto e branco,
ganharam cores e modo grá�co, um contexto no qual os pesquisadores da Xerox foram pioneiros, com a de�nição de
elementos que persistem até hoje nas interfaces grá�cas, como janelas, menus, caixas de opção, caixas de seleção e ícones. 
Em 1984, é lançado o primeiro produto de sucesso a utilizar
uma interface grá�ca, o computador pessoal Macintosh, da
Apple. Outras plataformas também disponibilizaram
ambientes baseados em janelas, como XWindow no UNIX e
Linux, Workbench no Amiga, GEM nos computadores Atari,
além do Windows, nos sistemas Microsoft. 
 Fonte: Shutterstock.
O papel do mouse é fundamental para a de�nição do modelo de usabilidade das interfaces grá�cas de usuário (GUI). Para os
computadores pessoais, o conjunto de componentes constituintes de uma GUI é denominado WIMP, formado pelas iniciais de
Window, Icon, Menu e Pointer, no qual o último se refere ao cursor grá�co com a posição controlada pelo mouse ou outro tipo
de dispositivo apontador, como o antigo trackball e os atuais touchpads.
Saiba mais
Esse modelo de usabilidade foi levemente modi�cado nos smartphones, já que as telas de toque não precisam da movimentação
de um cursor grá�co.
As informações da tela são organizadas em janelas e representadas através de ícones, com as funcionalidades sendo ativadas
por menus, assim como na arquitetura original, mas diversos outros componentes se popularizaram, como os botões e caixas
de seleção. Precisamos entender o objetivo e modo de utilização para os diversos componentes disponíveis, se quisermos
construir interfaces grá�cas consistentes.
Dica
Os nomes das classes que representam os componentes grá�cos variam de acordo com a biblioteca utilizada, mas sempre
mantendo a semântica. Com a biblioteca VCL, do Delphi, temos a classe TButton para representar um botão, enquanto no Java,
com a biblioteca SWING, temos JButton, apenas para citar um exemplo.
No ambiente do Java, temos diversas bibliotecas para a construção de GUI, como awt e swing, incluídas no JDK por padrão,
além de swt e JFX. Temos a descrição de alguns componentes no quadro a seguir.
AWT SWING Elemento Gráfico
Button JButton Botão de pressionar padrão
Label JLabel Etiqueta para exibição de texto estático
TextField JTextField Campo para entrada de texto
TextArea JTextArea Área de edição de texto com múltiplas linhas
CheckBox JCheckBox Campo de marcação on/off sem exclusividade
List JList Lista de valores selecionável
Choice JComboBox Lista de valores no estilo drop-down
Panel JPanel Painel para organização dos componentes
Com o uso de WIMP, os gerenciadores de janelas facilitam a interação entre representações grá�cas, aplicações e
gerenciamento de hardware, o que levou à adoção do nome desktop, devido à sensação proporcionada em sua utilização,
como uma mesa de trabalho.
No modelo web, muitos dos componentes do WIMP são mantidos, mas os
links modi�cam o conceito de navegação e a gerência de estados. Enquanto
no desktop temos a possibilidade de trabalhar com estados globais, mesmo
com a alternância de telas, a arquitetura web se baseia em um modelo de
requisição e resposta, eliminando o valor das variáveis antigas a cada vez
que uma nova página é desenhada.
Através do uso de JSF, temos uma solução web muito interessante no Java, que permite a utilização do modelo de gerência de
estados do desktop, mas implementa sistemas na arquitetura MVC de uma forma transparente. Esta aula é dedicada ao
modelo desktop, mas faremos uma introdução ao uso do JSF no decorrer da disciplina.
Construção de janelas
Para criarmos ambientes baseados em janelas no Java, sem componentes adicionais, podemos utilizar a biblioteca awt
(Abstract Window Toolkit) ou a swing. Enquanto a primeira lida com a API original para GUI, a segunda faz parte da JFC (Java
Foundation Classes), com uma série de vantagens em termos de velocidade e qualidade grá�ca.
Com o acréscimo de alguns pacotes, é possível utilizar o JFX, ambiente Java que viabiliza a construção de interfaces
multiplataforma avançadas através de arquivos XML e folhas de estilo. A grande vantagem desta biblioteca é a possibilidade de
criar telas com grande apelo multimídia e que podem ser executadas, sem alterações, em plataformas desktop, móvel e web.
 Disponível em: https://docs.oracle.com/javase/8/javafx/media-tutorial/overview.htm. Acesso em: 7 jul. 2020.
Uma quarta opção é a biblioteca swt (Standard Widget Toolkit), criada pela IBM e atualmente mantida pela Eclipse Foundation.
O ponto forte da swt é o uso de chamadas para a API do sistema em que executa, via JNI, utilizando a velocidade do núcleo da
plataforma, sem camadas intermediárias, além de manter o aspecto original dos componentes grá�cos do sistema.
Aqui utilizaremos a biblioteca swing, por ser um padrão do Java e pelos recursos grá�cos melhorados que os de componentes
awt. Existem muitas similaridades no uso destas bibliotecas, tanto em temos da organização dos componentes quanto no
tratamento de eventos.
Nessas duas bibliotecas, temos componentes visuais como botões, campos
de texto e listas, voltados para a interação com o usuário, e componentes
chamados de contêineres, responsáveis por agrupar os demais. O principal
contêiner é a janela, na qual são posicionados botões e demais
componentes visuais simples, além de painéis, que podem agrupar outros
componentes e painéis de forma recursiva.
A forma como os componentes serão dispostos sobre o contêiner deve ser controlada com o uso de classes que
implementam LayoutManager, em que cada uma de�ne um estilo de design, podendo ocorrer a combinação de estilos com a
utilização de painéis internos.
Layout Descrição
BorderLayout Aceita até cinco componentes, os quais devem ser posicionados em North, South, East, West e Center.
BoxLayout Coloca os componentes em uma linha ou coluna simples, podendo ser alinhados.
CardLayout Controlado por uma lista drop-down, permite exibir painéis de componentes de forma alternada.
FlowLayout Apenas coloca os componentes sequencialmente em uma linha, mas serve como base para os painéis de CardLayout.
GridBagLayout Sofisticado e complexo, divide o contêiner em um grid e depois permite mesclar células e adicionar espaços para o
posicionamento dos componentes.
GridLayout Trabalha com um grid simples,e os componentes vão preenchendo sequencialmente os espaços definidos.
Vamos criar uma primeira janela, contendo um campo de texto estático e dois botões, com posicionamento baseado em um
BorderLayout. Para a criação de uma janela, é necessário herdar da classe JFrame.
 
import java.awt.*;
import javax.swing.*;
 
public class ExemploJ001 extends JFrame {
 
private final JLabel texto;
private final JButton botao1;
private final JButton botao2;
 
public ExemploJ001() throws HeadlessException {
super("Primeiro Teste");
setLayout(new BorderLayout());
setBounds(10,10,300,200);
add(texto=new JLabel("Testando o JFrame"),"Center");
JPanel jp = new JPanel(new FlowLayout());
jp.add(botao1=new JButton("OK"));
jp.add(botao2=new JButton("Cancela"));
add(jp,"South");
}
 
public static void main(String[] args) {
new ExemploJ001().setVisible(true);
}
 
}
Após de�nir a classe da janela, acrescentamos os atributos referentes aos componentes visuais, que no caso são dois botões e
um texto estático. Como as instâncias não se modi�cam após a alocação no construtor, vamos marcá-los como �nal, que no
Java tem a conotação de constante.
No início do construtor de ExemploJ001, é invocado o construtor de JFrame e fornecido o texto com o título da janela. Em
seguida, escolhemos o tipo de layout (BorderLayout) e de�nimos o posicionamento e tamanho da janela com o uso de
setBounds, em que os parâmetros são as coordenadas x e y, além da largura e altura, nessa sequência.
Lembrando que o operador de atribuição retorna o valor atribuído no Java, cada componente visual de�nido nos atributos é
instanciado e, em seguida, adicionado ao contêiner. O texto estático é adicionado diretamente sobre o JFrame, na posição
Center, e os botões são adicionados sequencialmente a um painel com layout do tipo FlowLayout, sendo o painel adicionado ao
JFrame na posição South.
Nesse pequeno exemplo, é possível observar o modelo para a construção de GUI no Java, com base em gerenciadores de
layout para o posicionamento dos diversos componentes visuais e utilização de painéis para a de�nição de grupos de
componentes.
Comentário
Em termos de UML, a janela personalizada é de�nida a partir da herança de janela vazia e composição com os componentes
visuais.
Além da base da janela em JFrame, é possível utilizar JApplet, para permitir o uso da janela em uma página HTML, ou JDialog,
para a criação de janelas de diálogo personalizadas. O uso de applets é considerado obsoleto, mas ainda há muitos sites
�nanceiros que necessitam desta tecnologia para viabilizar criptogra�a forte do lado cliente.
Uma janela baseada em JDialog pode ser inicializada com a passagem de um componente owner, como um JFrame ou outro
JDialog. O atributo implementa uma hierarquia visual, com a de�nição de como as telas irão se sobrepor; se for nulo, o diálogo
sobrepõe todo o ambiente (modeless), sem um título especi�cado.
 
public class ExemploD001 extends JDialog{
private final JButton btnFechar;
public ExemploD001() {
setBounds(10,10,120,100);
setLayout(new FlowLayout());
add(new JLabel("Clique para fechar"));
add(btnFechar=new JButton("OK"));
}
public static void main(String[] args) {
new ExemploJ001().setVisible(true);
}
}
Por enquanto, não estamos implementando a interação com o usuário; logo, o clique sobre o botão não fechará realmente a
janela. Entretanto já será possível testar o design obtido com o código.
O fechamento de um diálogo, sem a programação adequada, não encerra o programa, o que irá gerar um novo processo a cada
execução solicitada, sendo necessário terminar os processos a partir do ferramental presente na parte inferior do editor do
NetBeans.
Apesar da possibilidade de criar diálogos personalizados, o componente JOptionPane já satisfaz boa parte das necessidades
usuais para a exibição de mensagens ou entrada de dados.
Método Descrição
showConfirmDialog Diálogo de confirmação no estilo "sim/não/cancela"
showInputDialog Solicitação de dados ao usuário
showMessageDialog Exibição de mensagem para o usuário
showOptionDialog Unificação dos outros três tipos
Os diálogos apresentados por JOptionPane podem ser utilizados tanto a partir de janelas swing quanto na linha de comando.
Com a adoção desses métodos, é possível substituir os comandos de entrada e saída do console.
 
import javax.swing.JOptionPane;
 
public class ExemploOptionPane {
 
public static void main(String[] args) {
int a = Integer.parseInt(
JOptionPane.showInputDialog("Primeiro Numero:"));
int b = Integer.parseInt(
JOptionPane.showInputDialog("Segundo Numero:"));
int c = a + b;
JOptionPane.showMessageDialog(null, "A soma será: "+c,
"Soma", JOptionPane.INFORMATION_MESSAGE);
}
}
No exemplo, temos duas chamadas para showInputDialog, com retorno de texto, convertido para inteiro através do uso de
parseInt e alimentando as variáveis a e b. A variável c recebe a soma dos valores, com a exibição do resultado através de
showMessageDialog.
Note que o parâmetro JOptionPane.INFORMATION_MESSAGE fará com que apareça o ícone de informação no uso de
showMessageDialog, podendo ser utilizados outros ícones.
Parâmetro Ícone
JOptionPane.INFORMATION_MESSAGE Informação comum
JOptionPane.ERROR_MESSAGE Indicativo de erro
JOptionPane.QUESTION_MESSAGE Interrogação (perguntas)
JOptionPane.WARNING_MESSAGE Sinal de atenção ou alerta
 Interação com Usuários
 Clique no botão acima.
Até agora, nós apenas criamos as janelas, mas não de�nimos como será a interação dos usuários com os componentes
visuais, como botões e itens de menu. Toda interação no swing é baseada no uso de interfaces ouvintes, do tipo EventListener,
modelo herdado dos componentes awt.
Listener Aplicação
ActionListener Reconhecimento de clique sobre botões e menus
DragSourceListener Início da operação de arrastar e soltar
DropTargetListener Final da operação de arrastar e soltar
FocusListener Controle de entrada e perda de foco, muito usado em campos de texto
ItemListener Modificação do estado para caixas de checagem e outros componentes selecionáveis
KeyListener Verificação de tecla pressionada ou liberada, bem como a junção dos dois (keyTyped)
MouseListener Controle do foco do mouse e pressionamento ou liberação dos botões
MouseMotionListener Movimentação do ponteiro do mouse
PopupMenuListener Modificação da visibilidade de menus de contexto
TextListener Reconhecimento de alterações no valor do texto
WindowListener Reconhecimento de ações gerais sobre as janelas, como abertura e fechamento
O momento em que ocorre a interação com o usuário é chamado de evento, sendo comum em qualquer plataforma com
suporte a GUI. Podemos de�nir evento como uma ação predeterminada que, ao ocorrer, permite que seja iniciada uma ação
personalizada, o que certamente será feito através de programação, no caso do Java, por meio das interfaces ouvintes.
Apesar da de�nição voltada para a prática, um evento é apenas a penúltima peça de toda a arquitetura. Uma interrupção ocorre
no nível da BIOS por conta do uso de um dispositivo de I/O, no qual o sistema operacional detecta e envia mensagens em
broadcast. Estas são interceptadas pelos diversos métodos de callback dos componentes, e se a mensagem é pertinente, são
ativados os métodos referentes ao evento associado, caso o ouvinte seja implementado pelo programador no último passo da
cadeia.
 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ExemploJ002 extends JFrame {
private final JTextField txtNome;
private final JCheckBox ckbEmail;
private final JButton btnOk;
public ExemploJ002() throws HeadlessException {
super("Exemplo com Evento Simples");
setBounds(10, 10, 400, 150);
setLayout(new GridLayout(3, 2));
txtNome = new JTextField(20);
ckbEmail = new JCheckBox("E-mail");
btnOk = new JButton("Adicionar");
add(new JLabel("Nome")); // [0,0]
add(txtNome); // [0,1]
add(new JLabel("Comunicação")); // [1,0]
add(ckbEmail); // [1,1]
add(btnOk); // [2,0]
btnOk.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent event) {
String frase = txtNome.getText() +
" optou por " + (ckbEmail.isSelected()?
"receber":"não receber")+" e-mail.";
JOptionPane.showMessageDialog(ExemploJ002.this, frase);
}
});
}
public static void main(String[] args) {
new ExemploJ002().setVisible(true);
}
}
Aqui utilizamos um GridLayout para organizar a janela, com três linhas e duas colunas, em que as células são preenchidas
sequencialmente, formando uma interface grá�ca com um campo de texto, uma caixa de checagem e um botão, além de dois
textos estáticos.
Com o clique sobre o botão, teremos a montagem da frase com o uso do valor digitado no campo de texto (getText) e uma
expressão alternativa obtida com base no valor da caixa de checagem (isSelected). A resposta ao evento de clique é de�nida
em uma implementação de ActionListener, no método actionPerformed, e a mensagem formada é exibida através de uma
chamada a showMessageDialog, de JOptionPane.
No código, foi utilizado o método addActionListener com a passagem da implementação de ActionListener, e esta era
considerada a maneira mais elegante para programar a resposta aos eventos no Java, mas as versões atuais permitem
também a adoção de expressão lambda.erformed, e a mensagem formada é exibida através de uma chamada a
showMessageDialog, de JOptionPane.
 
btnOk.addActionListener((ActionEvent event) -> {
String frase = txtNome.getText() + " optou por " +
(ckbEmail.isSelected()?"receber":"não receber")+
" e-mail.";
JOptionPane.showMessageDialog(ExemploJ002.this, frase);
});
Agora que conhecemos o processo de resposta ao clique, podemos alterar a classe ExemploD001, para que termine a
execução do programa. A operação lambda deve fazer uma chamada ao método exit de System.
 
public class ExemploD001 extends JDialog{
private final JButton btnFechar;
public ExemploD001() {
setBounds(10,10,120,100);
setLayout(new FlowLayout());
add(new JLabel("Clique para fechar"));
add(btnFechar=new JButton("OK"));
btnFechar.addActionListener((ActionEvent arg0) -> {
System.exit(0);
});
}
public static void main(String[] args) {
new ExemploD001().setVisible(true)
}
});
Até o momento, exploramos apenas o clique sobre os botões, meio mais utilizado de interação com o usuário, mas esta
interação pode ocorrer de outras formas, como pressionamento de teclas e movimentação do mouse, apenas a título de
exemplo. No decorrer desta aula, veremos a utilização de outros tipos de eventos, quando se tornarem adequados ao contexto.
Tela Cadastral
Vamos aproveitar as classes criadas na última aula e de�nir uma interface grá�ca para cadastramento. Como temos coleções
de entidades, precisamos entender o funcionamento de componentes multivalorados, como listas e tabelas, nos quais o uso de
modelos de preenchimento será obrigatório.
Na biblioteca awt, era possível preencher um componente de lista através de métodos diretos para adição de itens, mas swing
delega a tarefa para uma interface de preenchimento especí�ca, denominada ListModel. Com a mudança ocorrida, temos um
ambiente mais �exível para relacionar dados com a interpretação visual, na interface grá�ca.
 
public class ModelEmpresa extends AbstractListModel<Empresa>{
private final GestorEmpresa gestor = new GestorEmpresa();
private ArrayList<Empresa> listaEmpresas;
 
private void preencherLista(){
listaEmpresas = new ArrayList<>(gestor.obterTodos());
Collections.sort(listaEmpresas,
(Empresa e1, Empresa e2) ->
e1.getNome().compareTo(e2.getNome()));
}
public ModelEmpresa() {
preencherLista();
}
public void addEmpresa(Empresa empresa){
gestor.criar(empresa);
preencherLista();
fireIntervalAdded(this, getSize()-1, getSize()-1);
}
public void removeEmpresa(int index){
gestor.remover(getElementAt(index).getCNPJ());
preencherLista();
fireIntervalRemoved(this, index, index);
}
 
@Override
public int getSize() {
return listaEmpresas.size();
}
@Override
public Empresa getElementAt(int index) {
return listaEmpresas.get(index);
}
}
A classe ModelEmpresa deve conter os dados que serão incluídos no JList, no caso a coleção de empresas. Para tal,
instanciamos o gestor, criamos um ArrayList para conter os dados exibidos, e com o método preencherLista, atribuímos a
coleção retornada por obterTodos, ordenando as empresas por nome com o uso do método sort de Collections, no qual uma
expressão lambda de�ne a regra utilizada na ordenação.
No método addEmpresa, o gestor é utilizado para adicionar uma empresa à coleção global do repositório, enquanto em
removeEmpresa, a instância que ocupa a posição index na lista é removida do repositório. Em ambos os casos, a lista é
novamente preenchida, e o JList é sinalizado com o uso dos métodos �reIntervalAdded e �reIntervalRemoved.
A sobrescrita dos métodos getElementAt e getSize é obrigatória, em que o primeiro deve retornar o objeto na posição fornecida,
e o segundo retorna o tamanho da lista, complementando as lacunas existentes no desenho de um componente JList. Já o
construtor deve apenas efetuar a carga inicial da lista de dados.
 
public class ListagemEmpresa extends JFrame {
 
private final JList<Empresa> lista;
private final ModelEmpresa lstModel;
 
public ListagemEmpresa() throws HeadlessException {
super("Cadastro de Empresas");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(10,10,350,600);
lista = new JList<>(lstModel = new ModelEmpresa());
lista.setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);
Empresa e1 = new Empresa("11111");
e1.setNome("XEmpresa1");
Empresa e2 = new Empresa("22222");
e2.setNome("AEmpresa2");
lstModel.addEmpresa(e1);
lstModel.addEmpresa(e2);
add(lista);
}
 
public static void main(String[] args) {
new ListagemEmpresa().setVisible(true);
}
 
}
Aqui implementamos a janela principal, de nome ListagemEmpresa, com um componente do tipo JList e uma instância de
ModelEmpresa com o nome lstModel. No construtor, são de�nidas as características gerais da janela, inclusive o encerramento
a partir do clique no botão padrão para fechamento (EXIT_ON_CLOSE), e utilizamos o método addEmpresa para adicionar duas
empresas através de lstModel.
Quanto às con�gurações especí�cas do JList, temos a passagem de lstModel como parâmetro do construtor, associando o
modelo de preenchimento e a de�nição do modo de seleção unitária (SINGLE_SELECTION).
Executando o programa no atual ponto da codi�cação, poderemos observar a listagem com os endereços de memória das
duas empresas instanciadas.
A forma mais simples de apresentar o texto correto no JList é a modi�cação do método toString da classe Empresa. O método
de�ne como o objeto será expresso em termos de texto, tendo como padrão a exibição do nome completo da classe e
endereço de memória.
 
public class Empresa {
// Relação 1xN
private final List<Funcionario> funcionarios =
new ArrayList<>();
public List getFuncionarios(){
return funcionarios;
}
private String CNPJ;
private String nome;
public Empresa() {
}
public Empresa(String CNPJ) {
this.CNPJ = CNPJ;
}
 
@Override
public String toString() {
return nome+"::"+CNPJ;
}
 
// getters/setters
 
}
Executando novamente a classe principal, poderemos observar a exibição do nome e CNPJ de cada empresa, de forma
ordenada, mas nosso objetivo não é lidar com dados �xos, e sim promover a inclusão de empresas com os dados fornecidos
pelo usuário.
Inicialmente, vamos criar uma classe para o menu do sistema, com o nome MenuEmpresa, adicionando as opções para
inclusão de empresas, gestão dos funcionários e saída do sistema.
 
public class MenuEmpresa extends JMenuBar{
private final ListagemEmpresa janelaEmpresas;
private final JMenu mnCadastro;
private final JMenuItem mnEmpresaIncluir,
mnFuncionarios, mnSair;
public MenuEmpresa(ListagemEmpresa janela) {
super();
this.janelaEmpresas = janela;
mnEmpresaIncluir =
new JMenuItem("Incluir Empresa",KeyEvent.VK_E);
mnFuncionarios =
new JMenuItem("Funcionarios",KeyEvent.VK_F);
mnSair = new JMenuItem("Sair",KeyEvent.VK_S);add(mnCadastro = new JMenu("Cadastro"));
mnCadastro.setMnemonic(KeyEvent.VK_C);
mnCadastro.add(mnEmpresaIncluir);
mnCadastro.add(mnFuncionarios);
mnCadastro.add(mnSair);
configurarEventos();
}
private void configurarEventos(){
mnSair.addActionListener((ActionEvent event) -> {
System.exit(0);
});
}
}
Aqui temos a de�nição de um construtor que recebe a referência da janela principal, necessária em passos posteriores, sendo
instanciado um menu de primeiro nível com o texto "Cadastro" e três submenus de�nindo as opções "Incluir Empresa",
"Funcionarios" e "Sair". Todas as opções foram criadas com o uso de mnemônicos, ou seja, ativação pelo uso de ALT+tecla, em
que a tecla é escolhida pelo atributo estático em KeyEvent.
A classe JMenuBar serve de base para o menu, no qual as opções de
primeiro nível são con�guradas como JMenu e as de segundo nível como
JMenuItem
No código do construtor, após instanciar os elementos de menu, eles são organizados, adicionando o JMenu ao JMenuBar, e
os elementos do tipo JMenuItem ao JMenu. Ao �nal, é chamado o método con�gurarEventos, que inicialmente de�ne apenas a
resposta para a opção "Sair", com a saída do sistema, mas que concentrará todas as operações posteriores.
Para testar nosso menu, ele deve ser con�gurado na tela principal, com a inclusão de uma chamada a setJMenuBar e a
passagem da instância, logo após a linha que se chama setBounds.
 
setBounds(10,10,350,600);
setJMenuBar(new MenuEmpresa(this));
}
Com as modi�cações sugeridas até o momento, a janela irá exibir o menu, e os dados das duas empresas de teste serão
apresentados corretamente no componente JList.
A janela para inclusão de empresas será descendente de JDialog, com dois campos de texto e dois botões, sendo o
posicionamento de�nido através de um GridLayout.
 
public class InclusaoEmpresa extends JDialog{
private final JTextField txtNome = new JTextField(20);
private final JTextField txtCNPJ = new JTextField(20);
private final JButton btnConfirma = new JButton("Confirmar");
private final JButton btnCancela = new JButton("Cancelar");
private final ListagemEmpresa janelaEmpresas;
 
public Empresa getEmpresa(){
Empresa e1 = new Empresa(txtCNPJ.getText());
e1.setNome(txtNome.getText());
return e1;
}
public InclusaoEmpresa(ListagemEmpresa janela,
String titulo){
super(janela, titulo, true);
janelaEmpresas = janela;
setLayout(new GridLayout(3, 2));
setBounds(10,10,350,150);
setDefaultCloseOperation(HIDE_ON_CLOSE);
add(new JLabel("Nome")); add(txtNome);
add(new JLabel("CNPJ")); add(txtCNPJ);
add(btnConfirma); add(btnCancela);
btnConfirma.addActionListener((ActionEvent event) -> {
janelaEmpresas.addEmpresa(getEmpresa());
txtNome.setText("");
txtCNPJ.setText("");
});
btnCancela.addActionListener((ActionEvent event) -> {
setVisible(false);
});
}
}
Além de componentes visuais, temos uma referência para a janela principal, que é atribuída ao nível do construtor, juntamente
com o título. A referência será utilizada na resposta ao clique de btnCon�rma, com uma chamada ao método addEmpresa, que
deverá ser implementado na janela principal.
No clique da con�rmação, temos a obtenção de uma empresa com os dados de tela, através do método utilitário getEmpresa,
sendo o objeto utilizado na chamada para addEmpresa, da janela principal e a limpeza dos valores dos campos de texto na
sequência. Para o botão de cancelar, ocorre apenas o fechamento do diálogo, com a alteração da visibilidade.
Agora será necessário alterar ListaEmpresa, incluindo os métodos que serão utilizados para abrir o diálogo e acrescentar uma
empresa.
 
public class ListagemEmpresa extends JFrame {
private final JList lista;
private final ModelEmpresa lstModel; 
private InclusaoEmpresa janelaInclusao = null;
public void addEmpresa(Empresa empresa){
lstModel.addEmpresa(empresa);
}
public void abrirInclusao(){
if(janelaInclusao==null)
janelaInclusao = new InclusaoEmpresa(this,"Nova Empresa");
janelaInclusao.setVisible(true);
} 
public ListagemEmpresa() throws HeadlessException {
super("Cadastro de Empresas");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(10,10,350,600);
setJMenuBar(new MenuEmpresa(this));
lista = new JList<>(lstModel = new ModelEmpresa());
lista.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
add(lista);
} 
public static void main(String[] args) {
new ListagemEmpresa().setVisible(true);
}
}
Adicionamos um atributo do tipo InclusaoEmpresa na tela principal, além de um método para abrir a janela de inclusão. Note
que o atributo é iniciado com valor nulo, e é instanciado apenas na primeira chamada ao método de abertura, segundo o
princípio de inicialização tardia.
Certamente foi necessário implementar o método addEmpresa, chamado a partir do clique de con�rmação em
InclusaoEmpresa, e a adição da empresa é efetuada através de lstModel, repercutindo imediatamente no JList.
Ainda falta a chamada para o método abrirInclusao, que deverá ser feita a partir do menu, o que levará à modi�cação do
método con�gurarEventos.
 
private void configurarEventos(){
mnSair.addActionListener((ActionEvent event) -> {
System.exit(0);
});
mnEmpresaIncluir.addActionListener((ActionEvent event) -> {
janelaEmpresas.abrirInclusao();
});
}
Já podemos testar o programa, clicando na opção "Incluir Empresa" e vendo como a inclusão é re�etida de imediato no JList.
Como um de nossos objetivos é aproveitar os recursos do NetBeans, para a tela de gerência de funcionários, utilizaremos o
modelo de edição visual de GUI oferecido pela ferramenta.
Automatização com NetBeans
Além de syntax highlighting no editor, com a identi�cação dos tipos de comandos e estruturas através de cores, e
complementação automática de código, entre outras ferramentas de auxílio à codi�cação, o NetBeans traz um ambiente muito
prático para a criação visual de janelas swing e awt.
Para acrescentar uma janela do tipo JDialog ao nosso projeto, precisamos criar um novo arquivo, selecionar Swing GUI
Forms..JDialog Form, clicar em Next (Próximo) e dar um nome, no caso GerenciaFuncionarios. Com a janela criada, o editor
visual será aberto, exibindo as seguintes divisões:
Editor para posicionamento e dimensionamento de componentes; 
Paleta de componentes das bibliotecas swing e awt;
Editor com as propriedades para cada componente selecionado. 
A criação da tela segue um processo muito simples, baseada no arraste de componentes a partir da paleta para a área de
posicionamento. Para que a interface grá�ca apresente um nível de liberdade adequado, ela utiliza, por padrão, um gerenciador
do tipo GroupLayout, um modelo com alto nível de complexidade em termos de codi�cação, mas que permite posicionar os
componentes em qualquer região da tela.
Nossa tela terá um painel superior, no qual teremos alguns textos estáticos, os campos de entrada para matrícula
(txtMatricula), nome (txtNome) e data de nascimento (txtNascimento), além de três botões. Teremos um JTable na parte
inferior, com o objetivo de exibir os dados de consulta.
Através do painel Navigator, é possível modi�car o nome dos componentes e observar a estrutura hierárquica em termos
visuais, enquanto ocorrerá a modi�cação de propriedades, como text para os botões, com a seleção no editor ou no navegador,
e alteração de valor na divisão de propriedades.
Após o posicionamento e alterações de nomes e valores, os componentes �cam com a con�guração apresentada no quadro
seguinte, mas é claro que você pode experimentar a mudança de cores e fontes nas propriedades.
Componente Nome Valores
JPanel jPanel1 border=Etched Border
JLabel jLabel1 text="Matricula"
JLabel jLabel2 text="Nome"
JLabel jLabel3 text="Data de Nascimento"
JTextField txtMatricula text=""
JTextField txtNome text=""
JFormattedTextField txtNascimento text="" 
formatterFactory=date/short 
toolTipText="DD/MM/YYYY"
JButton btnIncluir text="Incluir"
JButton btnExcluir text="Excluir"
JButton btnConcluir text="Concluir"
O uso de um campo formatado para a data exigiráo preenchimento com a utilização do formato especi�cado, ou o valor não é
aceito. Acrescentamos um tooltip para mostrar o formato exigido quando o mouse repousa sobre o componente de entrada.
Programar nesse ambiente exigirá a utilização combinada do editor de telas e de código. Para começar, observe as três guias
na parte superior da área de edição, que permite alternar entre código (source), desenho (design) e histórico. Mudando para o
editor de código, será possível avaliar tudo o que foi gerado, com as partes de fundo cinza impedindo a edição do texto, além de
vários trechos ocultos, observáveis pelo salto na numeração das linhas, que são expandidos com o clique no sinal de adição.
Vamos começar as alterações necessárias, com o acréscimo dos gestores de funcionários e empresas, além de um atributo
para a empresa corrente.
 
public class GerenciaFuncionarios extends javax.swing.JDialog {
private GestorFuncionario gestorF = new GestorFuncionario();
private GestorEmpresa gestorE = new GestorEmpresa();
private Empresa empresa;
public Empresa getEmpresa() {
return empresa;
}
public void setEmpresa(Empresa empresa) {
this.empresa = empresa;
}
Para o preenchimento de um JTable, é necessário um JTableModel, mas neste caso utilizaremos o DafultTableModel, que
trabalha com elementos de texto simples.
 
private void preencherTabela(){
String[] colunas = {"Nome","Matricula","Nascimento"};
List<Funcionario> lista = getEmpresa().getFuncionarios();
Collections.sort(lista, (Funcionario f1, Funcionario f2) ->
f1.getNome().compareTo(f2.getNome()));
String[][] valores = {{"","",""}};
int tamanho = lista.size();
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
 
if(tamanho>0){
valores = new String[tamanho][3];
for(int i=0; i<tamanho; i++){
Funcionario f = lista.get(i);
valores[i][0] = f.getNome();
valores[i][1] = f.getMatricula();
valores[i][2] = df.format(f.getDataNascimento());
}
}
 
DefaultTableModel modelo =
new DefaultTableModel(valores,colunas);
jTable1.setModel(modelo);
}
No método prrencherTabela, temos a de�nição dos nomes de colunas através de um vetor e criamos uma matriz de texto para
os valores. Os dados são obtidos na lista de funcionários da empresa corrente, ordenando pelo campo nome, e a conversão de
data para o formato "DD/MM/YYYY" é feita com o uso de uma instância de SimpleDateFormat.
Se o tamanho da lista for maior que zero, a matriz é alocada para comportar esse tamanho, sendo executado um loop para
percorrer toda a listagem e preencher a linha da matriz a com os dados do funcionário de mesmo índice na lista, com cada
campo ocupando a coluna equivalente.
Ao �nal, é gerada uma instância de DefaultTableModel com as colunas e os valores de�nidos, substituindo o modelo corrente
de jTable1 com o uso do método setModel.
Para o preenchimento da JTable no momento correto, selecione JDialog no navegador, vá até o painel de propriedades, divisão
de eventos, abrindo o evento windowActivated. Você será direcionado para o código no trecho correto e terá apenas que
acrescentar a chamada para preencherTabela.
O método gerado terá o nome formWindowActivated e será invocado a partir da implementação do listener na parte não
editável do código. Note que não é possível editar a assinatura do método ou o fechamento do bloco.
 
private void formWindowActivated(java.awt.event.WindowEvent evt) {
preencherTabela();
}
Agora precisamos criar um método para a exibição da tela de funcionários a partir da tela principal.
 
private GerenciaFuncionarios funcionarios = null;
 
public void abrirTelaFuncionario(){
int index = lista.getSelectedIndex();
if(index>-1){
if(funcionarios==null)
funcionarios = new GerenciaFuncionarios(this, true);
funcionarios.setEmpresa(lstModel.getElementAt(index));
funcionarios.setTitle(
lstModel.getElementAt(index).getNome());
funcionarios.setVisible(true);
} else
JOptionPane.showMessageDialog(this, "Selecione a Empresa");
}
Como podemos observar, um atributo do tipo GerenciaFuncionarios foi acrescentado ao código de ListagemEmpresa, assim
como o método com o nome abrirTelaFuncionario, no qual instanciamos a janela se o valor ainda for nulo, obtemos a empresa
corrente a partir do JList, de�nimos a empresa da tela de funcionários com o método setEmpresa e �nalmente exibimos a tela.
Caso o JList não tenha uma empresa selecionada, um aviso é exibido com o uso de showMessageDialog.
O último passo é a modi�cação de MenuEmpresa para acrescentar uma chamada ao método abrirTelaFuncionario em
con�gurarEventos.
 
private void configurarEventos(){
mnSair.addActionListener((ActionEvent event) -> {
System.exit(0);
});
mnEmpresaIncluir.addActionListener((ActionEvent event) -> {
janelaEmpresas.abrirInclusao();
});
mnFuncionarios.addActionListener((ActionEvent event) -> {
janelaEmpresas.abrirTelaFuncionario();
});
}
Agora podemos voltar para a tela GerenciaFuncionarios e abrir o evento actionPerformed para cada um dos três botões, a partir
de propriedades. Para o método btnConcluirActionPerformed iremos apenas fechar a tela, com a alteração da visibilidade dela.
 
private void btnConcluirActionPerformed(ActionEvent evt) {
setVisible(false);
}
Para as ações de inclusão e remoção de funcionários, é interessante limpar a tela após o término. Para tal, vamos criar um
método utilitário de nome limparTela em GerenciaFuncionarios.
 
private void limparTela(){
txtMatricula.setText("");
txtNome.setText("");
txtNascimento.setText(null);
}
O clique do botão de remoção apresenta uma programação simples, com a remoção do funcionário no repositório, o que causa
a eliminação da relação com a empresa, a atualização dos valores da tabela e, ao �nal, a limpeza dos campos cadastrais.
 
private void btnExcluirActionPerformed(ActionEvent evt) {
gestorF.remove(txtMatricula.getText());
preencherTabela();
limparTela();
}
Com relação ao botão de inclusão, ele precisará de uma rotina um pouco mais complexa, inclusive com o tratamento de erros,
por conta da conversão de texto para data.
 
private void btnIncluirActionPertformed(ActionEvent evt) {
try {
Funcionario F = new Funcionario(txtMatricula.getText());
f.setNome(txtNome.getText());
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
f.setDataNascimento(df.parse(txtNascimento.getText()));
gestorF.criar(f);
gestorE.adicionarFuncionario(empresa, f);
preencherTabela();
limparTela();
} cath (ParseException ex) {
JOptionPane.showMessageDialog(this, "Erro ao Inserir");
}
}
No método, temos uma estrutura try..catch sobre todo o trecho referente à inclusão, e se ocorrer algum erro no bloco
protegido, exibimos a mensagem através de showMessageDialog.
O processo de inclusão envolve a criação de uma instância de Funcionario a partir dos dados digitados, em que a data de
nascimento deve ser convertida para Date através do método parse de SimpleDateFormat. Ao �nal da con�guração do objeto,
este deve ser inserido no repositório, com o método criar do gestor de funcionários, e utilizamos o método
adicionarFuncionario, do gestor de empresas, para associá-lo à empresa corrente.
Ao �nal do bloco, da mesma forma que na remoção, atualizamos os dados da tabela e limpamos os campos de entrada para
cadastro.
Já podemos testar as diversas funcionalidades de nosso sistema cadastral, mas lembrando que devemos executar
ListagemEmpresa, que atua como tela principal do programa.
Apenas para melhorar a usabilidade de nosso sistema, vamos implementar o evento mouseClicked para jTable1, o que é feito
através do painel de propriedades, e preencher a tela com os dados da linha que foi selecionada.
 
private void jTable1MouseEvent evt) {
int linha = jTable1.getSelectedRow();
if(linha > -1){
txtMatricula.setText(
jTable1.getValueAt(linha, 1).toString());
txtNome.setText(jTable1.getValueAt(linha, 0).toString());
txtNascimento.setText(
jTable1.getValueAt(linha, 2).toString());
}
}
O índice da linha selecionada é capturado com o uso de getSelectedRow, ea partir dele podemos obter os valores de jTable1
com getValueAt, tendo como parâmetros a linha e coluna da célula. Note que os dados das células são do tipo Object,
necessitando o uso de toString.
 Serialização e Persistência
 Clique no botão acima.
Quando os objetos são alocados, eles apontam para regiões esparsas na memória, pois cada atributo que também é objeto será
um novo ponteiro, apontando para outra região de memória. Esse é um modelo que apresenta di�culdades em termos de
armazenamento e transmissão de dados, pois não podemos emitir um espelho da memória completa.
O conceito de serialização visa solucionar o problema descrito, com a adoção de uma representação mais e�ciente. Na prática,
utilizamos um array de bytes para representar os dados contidos no objeto, constituindo uma estrutura contínua, que pode ser
armazenada no disco ou transmitida em rede com muita facilidade.
Ao falar de armazenamento dos dados no disco, devemos considerar mais um conceito, que se refere à possibilidade de um objeto
restaurar o estado armazenado anteriormente, e que é chamado de persistência.
Entidades persistentes, com gravação binária ou transmissão em rede, devem ser serializáveis.
Para que uma classe seja serializável na linguagem Java, somos obrigados a implementar a interface Serializable, que não contém
métodos, atuando apenas como um sinalizador para o compilador. Todos os atributos também devem ser serializáveis, algo que é
padrão para tipos nativos e Wrappers.
Vamos alterar nossas classes de Empresa e Funcionario, acrescentando a implementação de Serializable em suas assinaturas.
Com o acréscimo desta interface, nossas classes podem ser serializadas, da mesma forma que as coleções que as utilizem. O
único problema é que as ações de persistência ocorrem no nível do objeto, e as coleções do repositório estão no nível da classe
(static), sendo necessária uma classe de transporte. 
A nova classe terá o nome UnidadeGravacao, implementará Serializable e terá apenas dois atributos, para a recepção das coleções
do Repositório que representam funcionários e empresas. 
 
public class Empresa implements Serializable {
// Todo o código anterior é mantido
}
 
public class Funcionario implements Serializable {
// Todo o código anterior é mantido
}
 
public class UnidadeGravacao implements Serializable{ 
public HashMap<String, Funcionario> funcionarios; 
public HashMap<String, Empresa> empresas; 
public UnidadeGravacao( 
HashMap<String, Funcionario> funcionarios, 
HashMap<String, Empresa> empresas) { 
this.funcionarios = funcionarios; 
Agora podemos voltar à janela principal e acrescentar a armazenagem em disco. Vamos utilizar um componente do tipo
ObjectOutputStream, o qual trabalha diretamente com o valor do objeto serializado. 
O nome do arquivo onde ocorrerá a gravação é de�nido em nomeArq, mas poderia ser solicitado ao usuário com o uso de
showInputDialog ou de um componente do tipo JFileChooser. 
Veri�cando a implementação de gravarDados, podemos observar a criação de um ObjectOutputStream, com base em um
FileOutputSream, este último recebendo o nome do arquivo como parâmetro. O modelo adotado segue o padrão Decorator, no qual
temos o acréscimo de funcionalidades a cada nova camada, pois FileOutputStream consegue gravar apenas bytes no arquivo, mas
ObjectOutputStream acrescenta a possibilidade de gravar objetos. 
No início do código, temos uma instância de UnidadeGravacao iniciada com as coleções de interesse no repositório, e após a
con�guração de objOut, a instância é gravada com o uso de writeObject, seguido de �ush. Como o bloco está dentro de um try with
resources, o arquivo é sempre fechado ao �nal, e caso ocorra um erro, será exibida a mensagem do bloco catch. 
Resolvida a gravação, podemos cuidar da leitura, com um processo muito similar e mesmo nome de arquivo. 
this.empresas = empresas; 
} 
public UnidadeGravacao(){ } 
}
 
private final String nomeArq = 
"C:\\MeusTestes\\dadosEmpresa.objetos"; 
public void gravarDados() { 
UnidadeGravacao ug = new UnidadeGravacao( 
Repositorio.funcionarios,Repositorio.empresas); 
try (ObjectOutputStream objOut = new ObjectOutputStream( 
new FileOutputStream(nomeArq))) { 
objOut.writeObject(ug); 
objOut.flush(); 
} catch (IOException ex) { 
JOptionPane.showMessageDialog(this, "Erro ao Gravar");
}
 
public void lerDados() { 
try ( ObjectInputStream objIn = new ObjectInputStream( 
new FileInputStream(nomeArq))) { 
U id d G (U id d G ) bjI dObj t()
Na leitura, temos um FileInputStream apontando para o arquivo, seguido de um ObjectInputStream, para a leitura direta de objetos.
Com o uso de readObject, nós recuperamos o objeto, mas é necessário converter o tipo, pois o retorno do método é um Object. 
Com o objeto recuperado e convertido, substituímos as coleções envolvidas no repositório e chamamos o método atualizar, que
será de�nido na classe ModelEmpresa com o objetivo de sincronizar a exibição do JList. 
Agora só precisamos de algumas opções de menu para invocar as novas funcionalidades, levando a algumas inserções em
MenuEmpresa. Vamos adicionar alguns atributos e instanciá-los no construtor da classe, antes da chamada ao método
con�gurarEventos. 
UnidadeGravacao ug = (UnidadeGravacao) objIn.readObject(); 
Repositorio.funcionarios = ug.funcionarios; 
Repositorio.empresas = ug.empresas; 
lstModel.atualizar(); 
} catch (IOException | ClassNotFoundException ex) { 
JOptionPane.showMessageDialog(this, "Erro ao Ler"); 
} 
}
 
public void atualizar(){ 
preencherLista(); 
fireIntervalAdded(this, 0, getSize()-1); 
}
 
public class MenuEmpresa extends JMenuBar{ 
 
// Todos os atributos anteriores são mantidos 
 
private final JMenu mnPersistencia; 
private final JMenuItem mnGravar, mnLer; 
 
 
public MenuEmpresa(ListagemEmpresa janela) { 
 
// Todo o código anterior é mantido 
 
mnGravar = new JMenuItem("Gravar dados"); 
mnLer = new JMenuItem("Ler dados"); 
add(mnPersistencia = new JMenu("Persistencia")); 
Executando o programa, será possível observar a segunda família de opções de menu, mas ainda não con�guramos as respostas
ao clique. Por questões de simpli�cação, não foram de�nidos mnemônicos, mas você pode adicionar as teclas de acesso que
julgar convenientes. 
Para acrescentar a funcionalidade desejada nos menus, precisamos alterar mais uma vez o método con�gurarEventos de
MenuEmpresa. 
Como é possível observar, a alteração é bastante simples, com a chamada aos métodos criados em ListagemEmpresa, para a
persistência dos dados, a partir dos eventos de clique sobre as novas opções de menu. 
Após completar o código, execute o programa, insira alguns dados e mande gravar, pois encerrando e executando novamente,
bastará chamar a leitura para que sejam visualizados os dados antigos. 
mnPersistencia.add(mnGravar); 
mnPersistencia.add(mnLer); 
 
configurarEventos(); 
}
 
private void configurarEventos(){ 
 
// Todo o código anterior é mantido 
 
mnGravar.addActionListener((ActionEvent event) -> { 
janelaEmpresas.gravarDados(); 
}); 
mnLer.addActionListener((ActionEvent event) -> { 
janelaEmpresas.lerDados(); 
});
}
Atividade
1. Com as bibliotecas swing e awt, os componentes visuais são organizados através de elementos do tipo LayoutManager. Se
quisermos uma organização sequencial, qual gerenciador de layout devemos utilizar?
a) BorderLayout
b) GridBagLayout
c) CardLayout
d) FlowLayout
e) GridLayout
2. Em uma situação em que desejamos mostrar as coordenadas do cursor do mouse quando ele passar sobre um componente
de visualização de imagem, qual seria o Listener correto? 
a) ActionListener
b) KeyListener
c) MouseListener
d) MouseMotionListener
e) FocusListener
3. Em um sistema de registro de tarefas com persistência em arquivo, cada tarefa tem suas informações organizadas através de
uma instância de tarefa. Para que a entidade possa ser armazenada em disco, qual interface deve ser implementada? 
a) ActionListener
b) Runnable
c) KeyListener
d)Readable
e) Serializable
NotasReferências
CORNELL, G; HORSTMANN, C. Core Java. 8. Ed. São Paulo: Pearson, 2010. 
DEITEL, P; DEITEL, H. Java, como programar. 8. Ed. São Paulo: Pearson, 2010. 
FONSECA, E. Desenvolvimento de Software. Rio de Janeiro: Estácio, 2015. 
SANTOS, F. Programação I. Rio de Janeiro: Estácio, 2017.
Próxima aula
Persistência nos formatos JSON e XML;
Interoperabilidade via Middleware;
Utilização de banco de dados.
Explore mais
Acesse os seguintes links (em inglês): 
Tutorial do NetBeans para utilização do editor visual de janelas. Disponível em: https://netbeans.org/kb/docs/java/gui-
functionality.html. Acesso em: 7 jul. 2020. 
Processos assíncronos em janelas SWING. Disponível em: https:/www.kdgregory.com/index.php?page=swing.async.
Acesso em: 7 jul. 2020. 
Gerência de arquivos com bibliotecas New I/O. Disponível em: https://www.marcobehler.com/guides/java-�les. Acesso
em: 7 jul. 2020. 
javascript:void(0);
javascript:void(0);
javascript:void(0);

Outros materiais