-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
1/13
CAPTULO 11
Apndice - Mais swing e recursos
avanados
Com o que foi visto de Swing at agora, voc j deve conseguir
fazer diversas
outras brincadeiras apenas procurando mais recursos na API e
lembrando que,
trabalhando com Swing, sempre usaremos composio de
componentes!
Esse captulo mostra algumas outras modificaes que voc pode fazer
no
Argentum para torn-lo mais interessante. Alm disso, lendo mais
adiante voc
tambm conhecer um recurso poderoso ao lidar com processos
demorados dentro
do Swing.
11.1 - INPUT DE DADOS FORMATADOS: DATAS
Usar entrada de datas em um sistema Swing extremamente fcil:
podemos
usar a classe JTextField que permite obter e alterar os dados
digitados. Essa
classe muito flexvel tambm, possibilitando alterar vrios
aspectos da exibio
dos dados, dos formatos, dos eventos associados, etc.
No nosso sistema Argentum, vamos adicionar um campo para entrada
de data
que permita filtrar a lista de negcios usada para exibir a
tabela e o grfico.
Queremos um campo de texto com barras para separar campos da
data e , que
aceite apenas datas com formatao vlida. Uma classe filha de
JTextField j faz
boa parte desse trabalho: a JFormattedTextField.
Podemos criar um JFormattedTextField e associar a ele um
javax.swing.text.Formatter, como um DateFormatter, um
NumberFormatter
ou um MaskFormatter. Vamos usar o MaskFormatter para aplicar uma
mscara no
campo e permitir um input de datas fcil pelo usurio:
MaskFormatter mascara = new MaskFormatter("##/##/####");
mascara.setPlaceholderCharacter('_');
APOSTILA LABORATRIO JAVA COM TESTES, XML E DESIGN PATTERNS
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/http://www.caelum.com.br/?utm_source=Apostila_HTML&utm_campaign=FJ-16&utm_medium=referralhttp://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fwww.caelum.com.br%2Fapostila-java-testes-xml-design-patterns%2F
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
2/13
Repare na chamada ao setPlaceholerCharacter que diz ao
componente para
colocar um underscore nos espaos de digitao enquanto o usurio no
preenche
com a data desejada. Aps o usurio digitar, podemos obter o valor
chamando o
getValue. A partir da, podemos transformar o objeto em um Date
para uso:
11.2 - EXERCCIOS OPCIONAIS: FILTRANDO POR DATA
1. Abra a classe ArgentumUI e adicione a chamada ao
montaCampoData ao mtodo
montaTela (cuidado com a ordem):
2. Usando o ctrl + 1 na linha recm adicionada, indique para o
Eclipse que ele crie
esse novo mtodo (preparaCampoData). Implemente o mtodo como
abaixo,
prestando ateno no campoData, que deve ser um atributo (use o
Assign
statement to new field ou equivalente):
JFormattedTextField campoDataInicio = new
JFormattedTextField(mascara);
String valor = (String) campoDataInicio.getValue(); DateFormat
formato = new SimpleDateFormat("dd/MM/yyyy");
Date date = formato.parse(valor);
public void montaTela() {
preparaJanela(); preparaPainelPrincipal(); preparaAbas();
preparaTabela(); preparaPainelBotoes(); preparaCampoData();
preparaBotaoCarregar(); preparaBotaoSair(); mostraJanela();}
private void preparaCampoData() {
try {
JLabel labelData = new JLabel("Apenas a partir de:");
MaskFormatter mascara = new MaskFormatter("##/##/####");
mascara.setPlaceholderCharacter('_'); campoData = new
JFormattedTextField(mascara);
painelBotoes.add(labelData); painelBotoes.add(campoData); }
catch (ParseException e) {
e.printStackTrace(); }}
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
3/13
3. Rode a aplicao e veja o resultado:
4. Agora, precisamos implementar o filtro da data no momento de
carregar o XML.
Se o campoData estiver preenchido, adicione dentro do
carregaDados uma
chamada ao mtodo filtra de uma nova classe FiltradorPorData,
que
implementaremos na sequncia. Faa isso na linha logo aps a criao
da lista.
5. Vamos pedir que o Eclipse crie essa classe que recebe uma
dataDigitada no
construtor e a converte para um Calendar. Abuse do ctrl + 1 para
criar a classe e o
construtor. Complete a implementao do construtor:
private void carregaDados() {
List lista = new EscolhedorDeXML().escolhe();
if (campoData.getValue() != null) {
new FiltradorPorData(campoData.getText()).filtra(lista);
} ArgentumTableModel ntm = new ArgentumTableModel(lista);
//...
public class FiltradorPorData {
private Calendar dataInicial;
public FiltradorPorData(String dataDigitada) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
dataInicial = Calendar.getInstance();
dataInicial.setTime(sdf.parse(dataDigitada)); } catch
(ParseException e) {
throw new RuntimeException(e);
} }}
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
4/13
6. Estamos quase l! Agora, s falta criar o mtodo filtra que
passa pela lista de
negcios lida do XML removendo dela todos os negcios que sejam de
datas
anteriores data selecionada pelo usurio.
Dentro da ArgentumUI ainda deve haver um erro de compilao
informando de o
mtodo filtra ainda no existe na classe FiltradorPorData. Mande o
Eclipse
criar esse mtodo para voc e o complete com o cdigo para remover
os Negocios
de antes da data indicada.
Existe uma limitao da lista quando tentamos fazer uma remoo nela
dentro de
um lao que a percorre. Para conseguir fazer isso, usaremos o
Iterator:
7. Rode novamente sua aplicao e faa alguns testes. Teste
carregar sem a data
setada, setando uma data vlida, uma invlida, etc.
Iterator e remoes
Sempre use a classe Iterator quando precisar remover elementos
de uma
Collection enquanto percorre seus elementos.
8. (opcional) Repare que, ao colocar valores que extrapolem o
limite do campo (por
exemplo um ms 13), assumido que o primeiro ms do ano seguinte.
Para
public void filtra(List lista) {
if (dataInicial == null)
return;
Iterator it = lista.iterator(); while (it.hasNext()) {
if (it.next().getData().before(dataInicial))
it.remove(); } }
1
2
3
4
5
6
7
8
9
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
5/13
mudar esse comportamento, chame setLenient(false) no
SimpleDateFormat
que estamos usando.
O que acontece quando voc tenta filtrar uma data invlida
agora?
Trate a exceo no mtodo carregaDados, limpando o campoData e
dando uma
mensagem de pop-up para avisar o que aconteceu.
Seus livros de tecnologia parecem do sculo passado?
Conhea a Casa do Cdigo, uma nova editora, com autores de
destaque no mercado, foco em ebooks (PDF, epub, mobi),
preos imbatveis e assuntos atuais.
Com a curadoria da Caelum e excelentes autores, uma
abordagem diferente para livros de tecnologia no Brasil.
Conhea os ttulos e a nova proposta, voc vai gostar.
Casa do Cdigo, livros para o programador.
11.3 - PARA SABER MAIS: BARRA DE MENU
Para criar uma barra de menu no topo de nossas janelas, basta
usarmos a classe
JMenuBar do Swing. Dentro de um JMenuBar, colocamos vrios JMenu
que
representam cada menu (File, Edit, View Help etc). E, dentro de
cada JMenu,
colocamos vrios JMenuItems que representam cada ao (Abrir,
Salvar, Sair etc).
Existem ainda duas subclasses de JMenuItem, mais especficas,
que
transformam aquela entrada do menu em um checkbox ou radio
button,
JCheckboxMenuItem e JRadioButtonMenuItem.
public FiltradorPorData(String dataDigitada) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setLenient(false);
//...
JMenuBar menuBar = new JMenuBar();
janela.setJMenuBar(menuBar);
http://www.casadocodigo.com.br/?utm_source=Apostila_HTML&utm_campaign=FJ-16&utm_medium=referral
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
6/13
E podemos tratar os eventos desses menus da mesma forma que com
botes,
com ActionListeners.
11.4 - EXERCCIO: ESCOLHENDO INDICADORES PARA O GRFICO
Nosso grfico no nos d a chance de escolher quais indicadores
queremos ver.
Vamos, atravs de um JMenuBar, possibilitar ao usurio escolh-los.
Para isso,
criaremos uma barra de menu em uma classe auxiliar chamada
MenuIndicadores.
1. Na classe ArgentumUI, altere novamente o mtodo montaTela para
chamar o
mtodo preparaMenu logo abaixo da janela:
2. Faa o Eclipse criar esse mtodo para voc e o complete como
abaixo:
3. Crie o construtor da nova classe MenuIndicadores que o
Eclipse gerar para
voc atravs do ctrl + 1 e, nele, instancie cada um dos
indicadores possveis e crie
um JCheckBoxMenuItem para cada um deles. Para facilitar a
recuperao dos
objetos, guardaremos em um HashMap os itens do menu e seus
respectivos
indicadores.
JMenu menuInicio = new JMenu("Incio");
menuBar.add(menuInicio);
JMenu carregar = new JMenu("Carregar");
menuInicio.add(carregar);
JMenu sair = new JMenu("Sair");
menuInicio.add(sair);
JCheckBoxMenuItem check = new JCheckBoxMenuItem("Checkbox");
menuInicio.add(check);
public void montaTela() {
preparaJanela(); preparaMenu(); preparaPainelPrincipal();
preparaAbas(); preparaTabela(); preparaPainelBotoes();
preparaCampoData(); preparaBotaoCarregar(); preparaBotaoSair();
mostraJanela();}
private void preparaMenu() {
menu = new MenuIndicadores();
janela.setJMenuBar(menu.getMenuBar());}
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
7/13
Seu cdigo ficar parecido com esse:
4. No cdigo acima, voc deve ter notado que a barra de menu
menuBar foi
transformada em um atributo. Precisamos, agora, de um getter
para esse atributo.
Na classe MenuIndicadores, faa:
5. Rode sua aplicao e teste o menu, que, por enquanto no faz
nada:
6. Precisamos agora alterar o mtodo carregaDados para usar os
indicadores
selecionados no menu. Altere as linhas que tratam de chamar o
plotaIndicador
para iterar pela lista de indicadores selecionados:
public MenuIndicadores() {
List indicadores = new ArrayList();
indicadores.add(new IndicadorFechamento());
indicadores.add(new MediaMovelSimples(new
IndicadorFechamento()));
indicadores.add(new MediaMovelPonderada(new
IndicadorFechamento()));
// mais indicadores, se houver
menuBar = new JMenuBar();
JMenu menuIndicadores = new JMenu("Indicadores");
menuBar.add(menuIndicadores); indicadoresNoMenu = new
HashMap();
for (Indicador indicador : indicadores) {
JCheckBoxMenuItem opcaoIndicador = new
JCheckBoxMenuItem(indicador.toString(), true);
menuIndicadores.add(opcaoIndicador);
indicadoresNoMenu.put(opcaoIndicador, indicador); }}
getM
private void carregaDados() {
// algumas linhas...
GeradorDeGrafico gerador = new GeradorDeGrafico(serie, 2,
serie.getTotal()
- 1); List indicadores = menu.getIndicadoresSelecionados(); for
(Indicador indicador : indicadores) {
gerador.plotaIndicador(indicador);
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
8/13
7. Agora, s falta implementar esse mtodo
getIndicadoresSelecionados na
classe MenuIndicadores. Deixe que o Eclipse crie o cabealho do
mtodo para voc
e apenas o preencha verificando quais itens do menu foram
marcados
(item.isSelected()) e devolvendo os Indicadores de acordo.
8. Rode a aplicao novamente e teste escolher uma data e os
indicadores.
9. (opcional) Faa mais indicadores e adicione-os ao menu. Se for
necessrio, crie
mais menus para melhorar a usabilidade.
10. (opcional) Faa com que as aes e "Carregar XML" e "Sair"
tambm possam
ser executadas via alguma opo no menu bar.
} abas.setComponentAt(1, gerador.getPanel());}
public List getIndicadoresSelecionados() { ArrayList indicadores
= new ArrayList(); for (JCheckBoxMenuItem menuItem :
indicadoresNoMenu.keySet()) { if (menuItem.isSelected())
indicadores.add(indicadoresNoMenu.get(menuItem)); } return
indicadores;}
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por-
9/13
11.5 - DIFICULDADES COM THREADS E CONCORRNCIA
Quando rodamos uma aplicao com Swing/AWT, uma das maiores
dificuldades
trabalhar com threads. Isso porque temos que saber gerenciar o
desenho e
atualizao da tela ao mesmo tempo que queremos executar as lgicas
de negcio
pesadas e complexas.
Toda vez que rodamos uma aplicao Java, como sabemos, executamos
o mtodo
main na thread principal do programa. Quando rodamos um programa
com
Swing/AWT, uma nova thread criada, alm da principal, para tratar
do desenho da
interface e da interao do usurio.
Isso quer dizer que quando criamos listeners para eventos do
Swing, eles so
executados pela thread do AWT e no pela thread do main.
considerado m
prtica de programao executar tarefas pesadas (com muita conteno)
dentro
desses listener para no travar a thread do AWT e deixar a
interface com aparncia
de travada.
Faa o teste: pegue um XML de negocios bem grande (50 mil linhas
ou mais) e
mande seu programa carreg-lo. Ao mesmo tempo, clique no boto de
sair. Repare
que o evento demora muito para ser processado.
Quando formos executar operaes potencialmente pesadas, a boa
prtica que
o listener do evento no faa essa execuo, mas dispare uma nova
thread para
essa execuo. O problema que quando executamos alguma lgica de
negcios
muito comum ao final fazer alguma alterao nos componentes
visuais -- no
nosso programa, depois de processar o XML, precisamos atualizar
o TableModel
do JTable, por exemplo.
Mas toda atualizao nos componentes deve ser feita no AWT e no na
nova
thread, j que essa a nica forma de evitar completamente
problemas de
concorrncia: o AWT mantm uma fila de tarefas a serem processadas
e as executa
sem perigo de problemas de concorrncia.
Gerenciar essas threads todas e conseguir sincronizar tudo
corretamente,
executando tudo no seu devido lugar, um dos pontos mais
complexos do Swing. A
partir do Java 6 existe uma classe que procura simplificar esse
trabalho todo:
SwingWorker.
Agora a melhor hora de aprender algo novo
http://www.alura.com.br/
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por
10/13
Se voc gosta de estudar essa apostila aberta da Caelum,
certamente vai gostar dos novos cursos online que
lanamos na plataforma Alura. Voc estuda a qualquer
momento com a qualidade Caelum.
Conhea a Alura.
11.6 - SWINGWORKER
O princpio por trs da classe SwingWorker permitir executar
cdigos em uma
thread nova concorrentemente a outras tarefas da thread do AWT.
Essa classe traz
toda a infra-estrutura necessria para fazer a comunicao entre
essas threads de
forma segura.
Para faz-la funcionar, implementamos dois mtodos:
doInBackground() - contm o cdigo pesado que deve ser executado
na thread
concorrente. Pode devolver algum objeto que ser enviado para a
thread do AWT;
done() - executado na thread do AWT logo que o doInBackground
termina. Aqui
podemos recuperar o objeto devolvido na outra thread e atualizar
itens da
interface.
Temos que escrever uma classe que herda de SwingWorker e
implementar esses
mtodos. Na hora de extender o SwingWorker, precisamos passar
dois argumentos
para seu generics: o tipo do objeto que o doInBackground devolve
e um outro tipo
usado (opcionalmente) para indicar progresso (que no precisamos
agora).
Vamos ver uma implementao inicial:
public class CarregadorXMLWorker extends SwingWorker {
private final JTable tabela;
public CarregadorXMLWorker(JTable tabela)
this.tabela = tabela;
}
@Override protected List doInBackground() throws Exception {
return new EscolheXML().escolher();
}
http://www.alura.com.br/
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por
11/13
CAPTULO ANTERIOR:
Apndice: O processo de Build: Ant e Maven
PRXIMO CAPTULO:
Repare que o doInBackgroundno salva nada em atributos. O mtodo
done
obtm a lista de negcios a partir da chamada ao mtodo get. Isso
feito para
garantir thread-safety. Repare tambm que passamos a tabela como
argumento no
construtor, j que vamos precisar modific-la.
Barra de progresso e outras possibilidades
A classe SwingWorker traz ainda outros recursos mais avanados,
como a
capacidade de se implementar uma barra de progresso fazendo com
que a
thread em background notifique a thread do AWT sobre
pequenos
progressos feitos no seu processamento. Tudo de forma
thread-safe e
robusta.
11.7 - EXERCCIOS: PESQUISANDO MAIS NA API
1. Procure saber mais sobre o uso do SwingWorker nos tutoriais
da Oracle.
Esses tutoriais vm desde o tempo da Sun e trazem uma boa idia do
que o Swing
oferece aos desenvolvedores Java.
2. Outro ponto interessante so aqueles em que a API em si no nos
ajuda tanto
quanto gostaramos.
Felizmente, a comunidade do Java bastante forte e podemos tirar
proveito disso!
Procure, por exemplo, componentes open source que fazem abrir um
widget de
calendrio para escolhermos uma data.
@Override protected void done() {
NegociosTableModel model = new NegociosTableModel(get());
tabela.setModel(model); }}
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-o-processo-de-build-ant-e-maven/
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por
12/13
Apndice - Logging com Log4j
Voc encontra a Caelum tambm em:
Blog Caelum
Cursos Online
Facebook
Newsletter
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-logging-com-log4j/http://blog.caelum.com.br/?utm_source=Apostila_HTML&utm_campaign=FJ-16&utm_medium=referralhttp://www.alura.com.br/http://facebook.com/caelumbrhttp://www.caelum.com.br/newsletter/?utm_source=Apostila_HTML&utm_campaign=FJ-16&utm_medium=referral
-
14/7/2014 Apndice - Mais swing e recursos avanados - Laboratrio
Java com Testes, XML e Design Patterns
http://www.caelum.com.br/apostila-java-testes-xml-design-patterns/apendice-mais-swing-e-recursos-avancados/#11-2-exercicios-opcionais-filtrando-por
13/13
Casa do Cdigo
Twitter
http://casadocodigo.com.br/?utm_source=Apostila_HTML&utm_campaign=FJ-16&utm_medium=referralhttp://twitter.com/caelum