Apostila:Curso de java II

10

Click here to load reader

Transcript of Apostila:Curso de java II

Page 1: Apostila:Curso de java II

Curso de Java – Módulo IISwing

Fábio Mengue – [email protected] de Computação - Unicamp

Conceitos

Swing é um pacotede classesqueservemparaa construçãode GUI's (GraphicalUserInterface).O pacotefoi criadoem1997,e inclui tudoquesenecessitaparaa construçãodetelas,desdebotõesatétabelas.Além disso,os programasqueutilizam o Swing tem a capacidadedealterar sua interface(chamadode “Look and Feel”, em inglês), trabalharcom conceitosdeacessibilidade(parapessoascomdificuldadedevisãoou audição),imagens2D e suportea Dragand Drop entre aplicativos Java e nativos.

Importando pacotes Swing

Comotodo programaJava,temosqueindicar os pacotesde classesqueiremosutilizar.Normalmente temos que importar o pacote abaixo:

import javax.swing.*;

Mas a maioria dos programasSwing trata com eventos;portanto, tambémimportamosospacotes:

import java.awt.*;import java.awt.event.*;

Escolhendo o “Look and Feel”

Existem alguns “look and feel” que o programa pode usar: Java, Windows, CDE/Motif, eoutros. O código abaixo (em negrito) indica como uma aplicação especifica o “look and feel”:

...

public static void main(String[] args) {

try {

UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());

} catch (Exception e) { }

1

Page 2: Apostila:Curso de java II

...//Cria e mostra a GUI...

O código acima indica que o “look and feel” Java deve ser utilizado(CrossPlatform). Para utilizar outro (por exemplo, Windows), veja alinha abaixo:

UIManager.setLookAndFeel( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");

Temos ainda:

"com.sun.java.swing.plaf.motif.MotifLookAndFeel" (para CDE/Motif)“com.sun.java.swing.plaf.windows.WindowsLookAndFeel” (para Windows)“ javax.swing.plaf.mac.MacLookAndFeel” (para Mac).

O “look and feel” padrão(caso nenhumseja especificado)é o Java (tambémchamado de Metal).

Criando o Container e adicionando componentes

Todo programaSwing deve ter pelo menosum container(tambémchamadotop-levelcontainer).Normalmenteeleé um JFrame(umajanelacompleta,comdecorações).CadaJFramerepresentauma janela. O JFrameprovê o suporte para outros componentes,no tocante ahierarquia e trabalho com eventos.

O JFramepossuiduasdivisões.Uma delasé o ContentPane,que representaa partedajanelaondepodemosmontarnossaaplicação.O ContentPanenaverdadeé um JPanel,um outrocontainerque normalmenteé utilizado para recebercomponentesque fazemparte do mesmocontexto de layout. Isso é necessário para separar o design de partes da janela.

Segue um pedaço de código de exemplo:

public class MinhaAplicacao { ... public static void main(String[] args) { ... JFrame frame = new JFrame("Minha Aplicação"); //...cria os componentes e os insere no frame... frame.getContentPane().add(contents, BorderLayout.CENTER);

//Mostra o frame frame.addWindowListener(...); frame.pack(); frame.setVisible(true); }}

2

Page 3: Apostila:Curso de java II

No programaprincipal, a primeira linha cria o JFrame.Depoisde incluir os elementosdesejadosnaGUI, cria-seo gerenciadorde layout queindicaaoselementosdentrodo containercomo eles devem ser comportar.

Exemplos de componentes

Botões,CheckBoxes,RadioButtons,GruposdeBotões,ItensdeMenu,Ícones,CamposTexto,ToolTips,Bordas,ScrollPanes(barrasdescroll),Mini Editor (JTextPane),Combo(listasdrop-down),ListBoxes,TabbedPane(lista de arquivos),Caixasde Mensagem,Menus,JanelasPop-Up, Objetos de desenho,Caixas de Diálogo, Caixas de escolhade Arquivos, Sliders,Árvores, Tabelas, Áreas de Transferência (clipboard), entre outros.

Tipos de layout

Abaixo temos uma lista dos componentes mais utilizados na montagem de telas Swing.

BorderLayout: é o padrão.Divide a tela em cinco regiões(NORTH, SOUTH, EAST, WEST,CENTER). Todo componenteadicionadoentra automaticamenteno centro, “empurrando”osoutros para as bordas. Você pode incluir um componente em outra região como no exemplo:

...Container cp = getContentPane();cp.add(BorderLayout.NORTH, new JButton("North"));cp.add(BorderLayout.SOUTH, new JButton("South"));cp.add(BorderLayout.EAST, new JButton("East"));cp.add(BorderLayout.WEST, new JButton("West"));cp.add(BorderLayout.CENTER, new JButton("Center"));...

FlowLayout: é o mais simples.Ele simplesmente“enche” o containercom componentesdaesquerdapradireita,ataterminaro espaçoda linha. Daí, ele faz a mesmacoisana linha abaixo.Todos os componentessempreterão um espaçodo tamanhoque eles estãoocupandonomomento.

GridLayout: permiteconstruirumatabeladecomponentes.Ao adicioná-los,elessãocolocadosdaesquerdaparaa direitae decima parabaixoem umagrade.Você podeespecificaro númerode colunase linhas que serãonecessárias,e todasterão o mesmotamanho.Se existir menoscomponentesdo que o total de espaços,eles ficarão vazios. Caso contrário, o componenteexcedente não será mostrado. Por exemplo:...Container cp = getContentPane();cp.setLayout(new GridLayout(7,3));...

3

Page 4: Apostila:Curso de java II

GridBagLayout : permite maior controle que o GridLayout. Neste layout você pode definirexatamentecomoasregiõesdasuagradeirão secomportare reformatarcasoa janelatenhaseutamanhoalterado.Entretanto,é o gerenciadormaiscomplexode utilizar. Ele foi criadoparaserutilizado por programas de criação de GUI’s.

Absolute positioning: permite posicionamentoabsolutodos componentes.É uma das pioresmaneirasdegerenciaro layout,pois nãopermiteflexibilidadequandoa janelatemseutamanhoalterado. Para utiliza-lo:...Container cp = getContentPane();cp.setLayout(null);...E depois utilize o método setBounds() para cada um dos componentes, indicando onde ele iniciae termina. Basta adicionar ao container depois disso.

BoxLayout: é uma versãosimplificadado GridBagLayout.Permiteindicar a localizaçãodoscomponenteshorizontalmentee verticalmente,além de permitir o controle da distânciaentreeles. Veja o exemplo:...JPanel jpv = new JPanel();jpv.setLayout(new BoxLayout(jpv, BoxLayout.Y_AXIS));

for(int i = 0; i < 5; i++)jpv.add(new JButton("" + i));

JPanel jph = new JPanel();jph.setLayout(new BoxLayout(jph, BoxLayout.X_AXIS));

for(int i = 0; i < 5; i++)jph.add(new JButton("" + i));

Container cp = getContentPane();cp.add(BorderLayout.EAST, jpv);cp.add(BorderLayout.SOUTH, jph);...

O construtordo gerenciadorBoxLayouté diferentedosoutros.Você indicaum containerque deve ser gerenciadocomo um primeiro argumentoe a direçãodo layout como segundoargumento.

Conclusão:Swing é um pacotemuito poderoso.Poucaslinhas podemfazer muito. A grandeidéia aqui é misturaros gerenciadores,combinandoos simplescom os complexos.Entretanto,como todo desenhode GUI, é mais produtivo apelarparaum produtoquepermitao desenhocom mouse, sem perder tempo precioso desenhando tudo na base do codifica-compila-executa.

4

Page 5: Apostila:Curso de java II

Outros containers

Vimos que por vezes,para que o design saia certo, devemosutilizar vários layoutmanagerssimultaneamente.A utilização de qualquer subclassede Container permite queagrupemoscomponentesparaque elessejammostradose tratadoscomo apenasum conjunto.Normalmente, a preferência sempre recai sobre o JPanel.

Disparando eventos

A maioriadasaplicaçõesdeveter algunscomponentesqueapresentema telada maneiraque o usuárioquer ver. Essescomponentesmuitasvezessãoapenasinformativose um tantoinertes (como os labels, por exemplo), mas outros são criados com o propósito de realizar serviço(como os botões, por exemplo).

Devidoà naturezaorientadaa objetosdoJava,o códigoa serexecutadoquandoumbotãoé pressionadonormalmentepertencea outro objeto,quepossuia lógica denegócio.Esseobjetodeve ser um método, a ser invocado pelo botão quando este for clicado, por exemplo.

A maneiraJavade fazerissoé criando“ouvidores” (chamadosde Listeners),ligadosaobotão.Do pontodevista do botão,o Listeneré umalista de objetosa sereminvocadosquandoacontecerumaação(um clique de mouse,por exemplo).Do pontode vista do objeto,ele deveimplementarum métodocom um nomeespecial,e essemétodoseráinvocadoautomaticamentena chamada.

Tome como exemplo o código abaixo:...MeuExemplo Objeto = new MeuExemplo();...JButton button = new JButton("OK");button.addActionListener(Objeto);...

A partir de agora, quando button for clicado, ele irá realizar uma chamada a MeuObjeto.Temos uma lista de tipos de componentes e os eventos por eles gerados a seguir:

Evento Classes que geram esse eventoActionEvent JButton, JList, JTextField, JMenuItem,

JCheckBoxMenuItem, Jmenu, JPopupMenuAdjustmentEvent JscrollbarFocusEvent, KeyEvent, MouseEvent ComponentWindowEvent Window, including JDialog, JFileDialog,

JframeItemEvent JCheckBox, JCheckBoxMenuItem,

JComboBox, JlistTextEvent JTextComponent, JTextArea, JTextField

5

Page 6: Apostila:Curso de java II

Lidando com Eventos

O trabalhode lidar com eventosquasesempreacompanhaas aplicaçõesque utilizamSwing.Mesmoqueo aplicativonãotenhabotões,podeacontecero fechamentodajanela,o quepor si só é um evento.

Normalmenteexistembotõese camposdetexto,queeleslidamcomeventoscriandoumalista de objetosa sereminformados.Os objetos,por suavez, devemcriar um métodoespecialpara atender o evento. Veja o exemplo: class MeuExemplo implements ActionListener {... public void actionPerformed(ActionEvent e) { System.out.println (“Quem causou o evento foi “ + e.getSource()); }}

A classedeveimplementarumacertainterface.A palavrareservadaimplements exigequeessaclassedefinaum certométodoespecialqueseráexecutadoquandoo eventoocorrer.Aclassepodeimplementarvários Event Listeners,conseqüentementepossuindovários métodosespeciais. Temos uma lista deles:

Interface Métodos da interfaceActionListener actionPerformed(ActionEvent)AdjustmentListener adjustmentValueChanged(

AdjustmentEvent)ComponentListenerComponentAdapter

componentHidden(ComponentEvent)componentShown(ComponentEvent)componentMoved(ComponentEvent)componentResized(ComponentEvent)

FocusListenerFocusAdapter

focusGained(FocusEvent)focusLost(FocusEvent)

KeyListenerKeyAdapter

keyPressed(KeyEvent)keyReleased(KeyEvent)keyTyped(KeyEvent)

MouseListenerMouseAdapter

mouseClicked(MouseEvent)mouseReleased(MouseEvent)

MouseMotionListenerMouseMotionAdapter

mouseDragged(MouseEvent)mouseMoved(MouseEvent)

WindowListenerWindowAdapter

windowOpened(WindowEvent)windowClosing(WindowEvent) windowClosed(WindowEvent) windowActivated(WindowEvent)windowDeactivated(WindowEvent) windowIconified(WindowEvent) windowDeiconified(WindowEvent)

6

Page 7: Apostila:Curso de java II

Lidando com Threads

Se seu programa cria e utiliza a GUI normalmente, seu programa é dito “single threaded”.Isso quer dizer que apenascomponentesincluídos na mesmathread irão manipular a GUI,tornandodesnecessáriaa preocupaçãocoma situaçãoeventualemqueoutrathreadtenteacessara GUI ao mesmo tempo. A construção normal de um programa Swing segue o padrão abaixo:

public class MeuPrograma { public static void main(String[] args) { JFrame f = new JFrame(...); ...//Adicione os componentes... f.pack(); f.setVisible(true); //Não crie mais nada aqui. }

... //Toda a manipulação -- setText, getText, etc. -- //deve ser feita usando eventos como actionPerformed(). ...}

No códigoacima,a construçãoda GUI estána threadprincipal.VocêpodeconstruirsuaGUI em qualquerthread,desdeque você não faça nenhumachamadadepoisdo pack(), queaconteceapenasno métodomain(). A única instruçãoquedevevir apósé o setVisible().Essatécnica torna a aplicação “thread safe”.

Entretanto,a linguagemJava permite que se crie programasque utilizam múltiplasthreads.No casodaprogramaçãoSwing,sealgumdestescódigosafetara GUI quejá estávisívelsemutilizar os eventosprogramados(que é ondeo Javapara tudo paraesperaro retornodométodo), você tem um problema a mais a tratar.

Usando threads

A primeira regra parautilizar threadsé: evite usar threads.Elas são difíceis de lidar,tornamo programamaiscomplicadoparamanutençãoe aumentama chancedeerrosocorrerem.Tudo issoaconteceporqueo programadorpodeseesquecerde imaginarumacertasituaçãoquepodesimplesmentefazercom queo programaparede respondercasoum eventoocorra.Paraisso,deve-setomarprecauçõesparaquenenhumathreadcrie chamadasparaqualquermétododecomponente Swing. Se a chamada for necessária, ela deve ser feita através de um evento.

Apesardeseusperigos,o usode threadspodesermuito útil, e asvezes,imprescindível.Comofazercomquemeuaplicativocontinuerespondendoaousuárioao mesmotempoemqueme mostraum relógio ? Normalmenteas threadssãoutilizadasem casosondeo programadordesejaduas(ou mais) linhas de execução.Meu programapodecontaro tempo,aguardaruma

7

Page 8: Apostila:Curso de java II

interrupçãode uma fonte externade dadose ao mesmotempo responderaos comandosdousuário.

Veja o exemplo abaixo:... CapturaEvento ce = new CapturaEvento(); Button b = new Button(“OK”); b.addActionListener(ce);...

Definição de CapturaEvento:

... class CapturaEvento implements ActionListener { public void actionPerformed(ActionEvent e) { trataBotao(); } private void trataBotao() { int count = 0; while (true) { Thread.sleep(5); count++; } }...

O que deve acontecer no programa acima ? Ele funciona ?

Ao lidar como evento,o programairá executaro métodotrataBotao().Depoisde ficar 5segundos parado, incrementa o contador, e começa tudo novamente.

Notequeo programaquegerouo evento(e chamouo CapturaEvento)estáesperandoumretorno,que nuncairá acontecer,pois o loop feito no métodotrataBotao()é infinito. Paraousuário,a telasimplesmentecongela.Assim,o métodotrataBotao()devecontinuara contar,masa interface deve continuar a responder. Deve-se criar outra thread para resolver o problema.

A maneira mais fácil é gerando uma subclasse de Thread, como no exemplo abaixo:

public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; private int threadNumber = ++threadCount; public SimpleThread() { System.out.println("Making " + threadNumber); } public void run() {

8

Page 9: Apostila:Curso de java II

while(true) { System.out.println("Thread " + threadNumber + "(" + countDown + ")"); if(--countDown == 0) return; } } public static void main(String[] args) { for(int i = 0; i < 5; i++) new SimpleThread().start(); System.out.println("All Threads Started"); } }

Quandoestamosextendendoa classeThread,devemossobrecarregaro métodorun(),queé a porçãodecódigoqueirá serepetiremtodasasthreads.Temostambémmétodosparainiciare parar uma thread (start() e terminate()) Qual seria o resultado da execução do código acima ?

Agora podemosresolvero problemade nossoprogramausandoumathread.O truqueécolocaro nossoloop infinito dentrodeum métodorun().No casodenossoexemplocomSwing,poderíamos fazer algo do tipo:

... class CapturaEvento implements ActionListener { public void actionPerformed(ActionEvent e) { TrataBotao b = new TrataBotao(); } class TrataBotao extends Thread { TrataBotao() { start(); } void run() { int count = 0; while (true) { Thread.sleep(5); count++; } }...

SwingUtilities.invokeLater(getTextFieldText); ... System.out.println(myStrings[0] + " " + myStrings[1]);}

A utilização de Threadsimplica ainda no entendimentode acessosconcorrentesaomesmorecurso,que pode gerar um deadlockou mesmouma exceção.O Java possui uma

9

Page 10: Apostila:Curso de java II

maneirade controlaressascolisões.É a palavrareservadasynchronized. Ela evitaquemaisdeuma thread tenha acesso a um recurso ao mesmo tempo:

public synchronized void run() { while (true) { t1.setText(Integer.toString(count1++)); t2.setText(Integer.toString(count2++)); sleep(500); }

Existeaindacontrolede estadode threads(bloquear,parar,terminar,etc.), prioridades,métodos para notificar outras threads, que permite que controlemos nossas threads eimplementemosserviçostãocomplexosquantodaemons. Quandomal utilizadas,o mínimo queaconteceé queseuprogramafica lento.A complexidadee as“patologias”(comoacabarcomosrecursosdamáquina,entrarem condiçõesde corridae deadlock)muitasvezesjustificam a nãoutilização deste tipo de recurso. Mas esses assuntos fogem do escopo deste curso.Recomendamos a leitura da bibliografia indicada para maiores informações.

Bibliografia

The Java Tutorial – http://www.sun.com/docsEckel, Bruce. Thinking in Java, 2nd edition, Revision 12Horstmann, Cay S., Cornell, Gary. Core Java. Makron Books

Proibida a alteração, reprodução e cópia de parte deste material para qualquer finalidade sem a permissão do Centrode Computação da Unicamp.

A utilização deste material é permitida desde que conste a autoria do mesmo.

� 2002 Centro de Computação da Unicamp.

10