gu - ajax em java sem html nem javascript usando

Upload: bergpb

Post on 11-Jul-2015

58 views

Category:

Documents


0 download

TRANSCRIPT

Maurcio Linhares de Arago Junior http://maujr.org/

AJAX em Java sem HTML nem JavaScript usando ThinwireMaurcio Linhares de Arago JuniorDesenvolva aplicaes web utilizando tcnicas AJAX sem ter que escrever nenhuma linha de HTML ou JavaScript, utilizando a biblioteca de componentes para web Thinwire

IntroduoO Thinwire um framework para o desenvolvimento de aplicaes web utilizando tcnicas AJAX baseado em componentes visuais, como as bibliotecas grficas para desktop como Swing ou SWT. Nele, todo o seu cdigo escrito em Java e uma aplicao web gerada baseada no que voc programou. Diferentemente de outros frameworks para o desenvolvimento AJAX em Java, como o Google Web Toolkit, o Thinwire no utiliza de forma alguma geradores de cdigo ou transformaes, todo o cdigo sempre escrito em Java e executa normalmente dentro de qualquer servidor web Java. Antes de iniciar o tutorial voc deve fazer o download do Thinwire na pgina oficial do projeto: http://www.thinwire.com/ , se j usa o Java 1.5 ou mais recente, pode baixar a verso prpria para o Java 1.5 e basta apenas adicionar o JAR do commons-fileupload que est dentro do download do SDK do Thinwire, se voc usa uma verso anterior ao Java 1.5, deve colocar todos os arquivos JAR que esto no SDK do Thinwire no seu classpath.

Se voc utiliza o Maven 2 para gerenciar o seus projetosSe voc utiliza o Maven 2 para gerenciar os seus projetos, vai preceber que os arquivos do projeto existe uma pasta chamada maven, nela voc vai encontrar uma pasta project com os arquivos do projeto do Maven 2 (incluindo um pom.xml) e uma pasta repository que contm a dependncia do Thinwire configurada. A nica configurao adicional que voc precisa fazer adicionar a dependncia do Thinwire no seu repositrio, para fazer isso, basta copiar a pasta que est dentro da pasta repository dos arquivos do projeto para dentro do seu repositrio local do Maven 2. Se voc no sabe o que o Maven 2, pode saber mais no tutorial Automatizando os seus projetos com o Maven 2 (http://guj.com.br/java.tutorial.artigo.185.1.guj )

Ol Mundo!Para comear os nossos estudos, vamos para o caso clssico de Ol mundo. Ns vamos criar uma janela (com o component Dialog) e nessa janela ns vamos adicionar um componente Label com o nosso texto. Listagem 1 Ol Mundo com o Thinwire

public class Main { public static void main(String[] args) { Application.current().getFrame().setTitle("Ol Mundo No Thinwire!"); Dialog dialog = new Dialog(); dialog.setTitle("Janela"); dialog.setBounds(100, 100, 400, 200); Label label = new Label(); label.setText("Ol Mundo Pelo Thinwire!"); label.setSize( 150, 50 ); dialog.getChildren().add(label);GUJ http://www.guj.com.br Pgina 1

Maurcio Linhares de Arago Junior http://maujr.org/

dialog.setVisible(true); } }O exemplo mostra um uso simples do Thinwire, na primeira linha ns acessamos a uma referncia da aplicao corrente (a que est disponvel para o usurio atual), depois acessamos o objeto Frame da aplicao, que a tela (ou aba) do navegador que est mostrando a aplicao, e alteramos o ttulo dele. Aps essa alterao, criamos um objeto do tipo Dialog (uma janela), criamos um Label e adicionamos ele a janela e no fim do cdigo ns alteramos a propriedade visible da janela para que ela torne-se visvel. O cdigo extremamente simples e parecido com qualquer outro cdigo de desenvolvimento de interfaces grficas para desktops que voc j tenha desenvolvido, a nica diferena que esse cdigo para o desenvolvimento de aplicaes web que usam AJAX. As nicas partes diferentes que ns podemos perceber quando em vez de usar o mtodo setSize() na janela, ns usamos o mtodo setBounds(), que posiciona o componente de forma absoluta em seu componente pai e no de forma relativa. Os dois primeiros parmetros do mtodo so as posies x e y iniciais no plano cartesiano representado pelo componente pai, que no nosso caso o prprio Frame da janela do navegador. Se esses valores houvessem sido definidos em um componente com outro pai, esses valores teriam sido absolutos com relao ao atual pai do componente. Todos os componentes no Thinwire devem, obrigatoriamente, ter um tamanho, se voc adicionar um componente sem colocar o seu tamanho ele simplesmente no vai ser desenhado na tela. Para podermos implantar essa aplicao web em um servidor web Java comum, ns precisamos configurar ela no web.xml da aplicao web, vejamos como seria essa configurao do web.xml: Listagem 2 web.xml do primeiro exemplo

thinwire thinwire.render.web.WebServlet styleSheet DefaultStyle mainClass org.maujr.thinwire.hello.Main thinwire /* O web.xml em questo define um servlet do Thinwire que responsvel por carregar a nossa aplicao. Na configurao do servlet ns passamos as informaes pelos valores dos init-param, o parmetro mainClass diz qual a classe que tem o mtodo public static void main (String[] args), essa classe que define o ponto de entrada de nossa aplicao e atravs dela que o Thinwire comea a inicializao do cdigo. O segundo parmetro, styleSheet, define o estilo visual que os componentes do Thinwire devem mostrar para o usurio, algo como um skin do seu sistema operacional. Ns definimos como estilo o DefaultStyle que o estilo padro da ferramenta. A pasta DefaultStyle deve estar no diretrio raiz daGUJ http://www.guj.com.br Pgina 2

Maurcio Linhares de Arago Junior http://maujr.org/

sua aplicao web para que ela possa ser utilizada pelo Thinwire dentro da sua aplicao. Os arquivos necessrios para o DefaultStyle vem dentro do arquivo JAR do Thinwire e voc tambm pode encontralos nos arquivos do projeto do tutorial. Vejamos ento a tela do nosso primeiro exemplo: Imagem 1 Ol Mundo no Thinwire

Labels e campos de entrada de textoAgora que j vimos o que necessrio configurar para fazer uma aplicao Thinwire executar, vejamos como utilizar os componentes de entrada de texto disponveis no toolkit. Como campos de entrada para o usurio, ns temos: Label Campo de texto que normalmente serve para explicar um outro componente; TextField Componente que desenha um campo de texto simples de uma nica linha, que pode ter uma mscara e tambm funcionar como um campo do tipo password, onde o texto escrito escondido do usurio; TextArea Componehte que desenha um campo de texto que pode ter vrias linhas de texto; DateBox Componente que desenha um calendrio para que o usurio possa selecionar uma data (tambm j o DropDownDateBox que um DateBox dentro de um componente DropDown);

Vejamos um exemplo de cdigo do uso desses componentes: Listagem 3 Exemplo de labels e inputs

public static void main(String[] args) { Entrada"); Application.current().getFrame().setTitle("Exemplo de Campos de

GUJ http://www.guj.com.br Pgina 3

Maurcio Linhares de Arago Junior http://maujr.org/

Dialog dialog = new Dialog(); dialog.setTitle("Exemplo de Campos de Entrada"); dialog.setModal(false); dialog.setResizeAllowed(true); dialog.setBounds( 50, 50, 300, 200 ); Label labelInput = new Label(); labelInput.setBounds( 10, 10, 100, 20 ); labelInput.setText("InputText"); TextField inputField = new TextField(); inputField.setBounds(60, 10, 100, 20); Label labelPassword = new Label(); labelPassword.setBounds( 10, 40, 100, 20 ); labelPassword.setText("Password"); TextField inputPassword = new TextField(); /* Colocar a propriedade inputHidden com o valor TRUE faz * com que o componente no exiba o seu texto */ inputPassword.setInputHidden(true); inputPassword.setBounds(60, 40, 100, 20); Label labelMask = new Label(); labelMask.setBounds( 10, 70, 100, 20 ); labelMask.setText("Masked"); TextField inputMask = new TextField(); inputMask.setBounds(60, 70, 100, 20); /* Para criar um editor com mscara, basta dizer * qual o formato na propriedade editMask */ inputMask.setEditMask("##,##"); dialog.getChildren().add(labelInput); dialog.getChildren().add(inputField); dialog.getChildren().add(labelPassword); dialog.getChildren().add(inputPassword); dialog.getChildren().add(labelMask); dialog.getChildren().add(inputMask); dialog.setVisible(true); }Como voc pode perceber, o exemplo segue a mesma lgica do anterior, ns criamos os componentes, damos uma posio a eles atravs da chamada do mtodo setBounds(), se ns no tivssemos feito as chamadas ao mtodo setBouds() dos componentes, todos eles teriam sido desenhados na posio 0,0 do seu componente pai e apareciam todos um por cima dos outros, por isso necessrio posicionar todos absolutamente dentro dos seus componentes pai. No fim do exemplo ns adicionamos os componentes na janela e alteramos a propriedade visible da janela para que ela fique visvel. As nicas partes diferentes deste cdigo, so o incio, onde alteramos algumas propriedades da janela (o objeto Dialog), ns fazemos com que ela seja no modal e que possa ter o seu tamanho alterado pelo usurio. Aps isso, criamos um TextField alterando a sua propriedade inputHidden para transforma-lo em um campo que esconde o que o usurio digitou e no terceiro TextField ns alteramos a propriedade editMask para que ela formate a entrada que o usurio digitar. Imagem 2 Imagem com o exemplo dos componentes de texto

GUJ http://www.guj.com.br Pgina 4

Maurcio Linhares de Arago Junior http://maujr.org/

Vejamos como est o nosso arquivo de configurao agora: Listagem 5 Arquivo de configurao das aplicaes do Thinwire

helloworld thinwire.render.web.WebServlet mainClass org.maujr.thinwire.hello.Main styleSheet DefaultStyle helloworld /* GUJ http://www.guj.com.br Pgina 5

Maurcio Linhares de Arago Junior http://maujr.org/

text thinwire.render.web.WebServlet styleSheet DefaultStyle mainClass org.maujr.thinwire.text.Main text /text Agora ns temos duas aplicaes do Thinwire configuradas. Devido a um bug ainda no resolvido na verso utilizada desse tutorial (a 1.2rc1), necessrio que sempre haja uma aplicao mapeada para a URL /*, ento, se voc vai colocar vrias aplicaes do Thinwire em uma nica aplicao web, lembrese sempre de adicionar uma delas mapeada para o contexto raiz em /*, as outras aplicaes podem ter as suas URLs normalmente (o mapeamento genrico no vai afetar o seu funcionamento). Voc tambm pode simplesmente mapear o mesmo servlet para dois caminhos de URL distintos. Vejamos agora um exemplo que use TextBoxes e os campos de entrada de data: Listagem 4 Exemplos de labels, TextBoxes e DateBoxes

public static void main(String[] args) {

Application.current().getFrame().setTitle("Exemplo de Campos de Entrada"); Dialog dialog = new Dialog(); dialog.setTitle("Exemplo de Campos de Entrada"); dialog.setModal(false); dialog.setResizeAllowed(true); dialog.setBounds( 50, 50, 400, 400 ); Label labelArea = new Label(); labelArea.setBounds( 10, 10, 100, 20 ); labelArea.setText("TextArea"); final Label labelResult = new Label(); labelResult.setBounds( 170, 10, 100, 100 ); labelResult.setWrapText(true); labelResult.setText(""); TextArea textArea = new TextArea(); textArea.setBounds(60, 10, 100, 100); textArea.addPropertyChangeListener( TextComponent.PROPERTY_TEXT , new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent ev) { labelResult.setText( ev.getSource()).getText() ); } }); Label labelDate = new Label(); labelDate.setBounds(10, 120, 100, 20);GUJ http://www.guj.com.br Pgina 6

((TextComponent)

Maurcio Linhares de Arago Junior http://maujr.org/

labelDate.setText("Date"); DateBox dateBox = new DateBox(); dateBox.setBounds(60, 120, 100, 150); Label labelDateDropDown = new Label(); labelDateDropDown.setText("DropDate"); labelDateDropDown.setBounds(10, 280, 100, 20); DropDownDateBox dropDownDateBox = new DropDownDateBox(); dropDownDateBox.setBounds(60, 280, 100, 20); dialog.getChildren().add(labelArea); dialog.getChildren().add(textArea); dialog.getChildren().add(labelResult); dialog.getChildren().add(labelDate); dialog.getChildren().add(dateBox); dialog.getChildren().add(labelDateDropDown); dialog.getChildren().add(dropDownDateBox); dialog.setVisible(true); }Neste exemplo, temos de novo os componentes que desenham calendrios para que o usurio possa selecionar uma data. Alm dos componentes de data, ns tambm criamos um listener, que um objeto que responde a um evento, e registramos ele no evento de alterao da propriedade text do TextArea, pois assim, a cada vez que algum digitar alguma coisa naquele componente o cdigo vai receber o evento e vai escrever o atual valor do TextArea em um Label que est ao seu lado. Imagem 3 Imagem do exemplo de uso de TextAreas e Dates

GUJ http://www.guj.com.br Pgina 7

Maurcio Linhares de Arago Junior http://maujr.org/

Lidando com botesO Thinwire define os trs tipos mais comuns de botes, o boto comum de clicar, o checkbox, que um boto que serve como um marcador e os botes de radio, que funcionam como uma lista onde voc pode selecionar um nico valor. Vejamos o nosso exemplo de cdigo: Listagem 5 Exemplo do uso de botes

public static void main(String[] args) { Application.current().getFrame().setTitle("Exemplo de Botes"); Dialog dialog = new Dialog(); dialog.setTitle("Exemplo de Botes"); dialog.setModal(false); dialog.setResizeAllowed(true); dialog.setBounds( 50, 50, 400, 400 ); Button button = new Button(); button.setText("Clique Aqui!"); button.setBounds(50, 50, 100, 30); { button.addActionListener( Button.ACTION_CLICK , new ActionListener() public void actionPerformed(ActionEvent ev) { Button button = (Button) ev.getSource(); if ( "Clique Aqui!".equals( button.getText()) ) {GUJ http://www.guj.com.br Pgina 8

Maurcio Linhares de Arago Junior http://maujr.org/

} } );

button.setText("Clique Ali!"); } else { button.setText("Clique Aqui!"); }

CheckBox checkBox1 = new CheckBox(); checkBox1.setText("Opo 1"); checkBox1.setBounds(50, 90, 100, 30); CheckBox checkBox2 = new CheckBox(); checkBox2.setText("Opo 2"); checkBox2.setBounds(50, 130, 100, 30); CheckBox checkBox3 = new CheckBox(); checkBox3.setText("Opo 3"); checkBox3.setBounds(50, 170, 100, 30); RadioButton radio1 = new RadioButton(); radio1.setText("Radio 1"); radio1.setBounds(50, 230, 100, 30); RadioButton radio2 = new RadioButton(); radio2.setText("Radio 2"); radio2.setBounds(50, 270, 100, 30); RadioButton.Group radioGroup = new RadioButton.Group(); radioGroup.add(radio1); radioGroup.add(radio2); dialog.getChildren().add(button); dialog.getChildren().add(checkBox1); dialog.getChildren().add(checkBox2); dialog.getChildren().add(checkBox3); dialog.getChildren().add(radio1); dialog.getChildren().add(radio2); dialog.setVisible(true); }A criao de componentes igual a que ns j havamos visto antes, a nica diferena que ns podemos notar nesse cdigo a forma que o ActionListener implementado. Ele no registrado simplesmente para o evento de clique do boto, mas para um tipo de clique, que o clique simples, se o evento fosse para o clique duplo, o evento utilizado seria o Button.ACTION_DOUBLE_CLICK. Ento, no nosso caso, a cada vez que o usurio clicar no boto, o evento vai ser chamado. Outro detalhe importante o objeto RadioButton.Group, que serve para agrupar um conjunto de RadioButtons, atravs dele que ns garantimos que apenas um dos RadioButtons est selecionado em uma interface. Aps criar os RadioButtons ns adicionamos eles no Group para que eles possam ser utilizados corretamente. Imagem 4 Exemplo do uso de botes

GUJ http://www.guj.com.br Pgina 9

Maurcio Linhares de Arago Junior http://maujr.org/

Painis com abas - TabFoldersPainis com abas so comuns em aplicaes, eles costumam representar opes de configuraes, vrios documentos abertos (como em navegadores que tem suporte a abas). Vejamos como criar painis com abas no Thinwire: Listagem 6 Exemplo do uso de TabFolders

public static void main(String[] args) { Abas"); Application.current().getFrame().setTitle("Exemplo de Painis com Dialog dialog = new Dialog(); dialog.setTitle("Exemplo de Painis com Abas"); dialog.setBounds(100, 100, 400, 400); TabFolder tabFolder = new TabFolder(); tabFolder.setSize(300, 300); TabSheet firstTabSheet = new TabSheet();; firstTabSheet.setText("Aba 1"); Label label = new Label(); label.setText("Label na primeira Aba"); label.setSize(150, 30); firstTabSheet.getChildren().add(label); TabSheet secondTabSheet = new TabSheet(); secondTabSheet.setText("Aba 2"); Button button = new Button(); button.setText("Button na segunda aba"); button.setSize(150, 30); secondTabSheet.getChildren().add(button); tabFolder.getChildren().add(firstTabSheet); tabFolder.getChildren().add(secondTabSheet); dialog.getChildren().add(tabFolder); dialog.setVisible(true); }GUJ http://www.guj.com.br Pgina 10

Maurcio Linhares de Arago Junior http://maujr.org/

O componente que representa o container de abas o TabFolder, cada aba um objeto do tipo TabSheet. Para adicionar um componente em uma das abas, basta usar a referncia para o TabSheet no qual voc deseja adicionar novos componentes e adicion-los a a sua lista. Voc pode selecionar uma aba especfica usando o mtodo setCurrentIndex() da classe TabFolder, passando como parmetro o ndice da TabSheet que voc deseja selecionar. Imagem 5 Exemplo do uso de painis com abas

Mostrando dados na forma de tabelasExibir informao na forma de tabelas lugar comum na maioria das aplicaes desenvolvidas, seja qual for o seu trabalho real. Tabelas bem organizadas facilitam at mesmo o entendimento do que est sendo mostrado por parte dos usurios, ento um bom framework de interface no poderia deixar de ter um componente tabela para mostrar informaes. O componente que representa as tabelas no Thinwire o GridBox, que alm de mostrar os dados de forma tabular, tambm torna possvel a seleo de suas linhas, vejamos um exemplo do uso desse componente: Listagem 7 Exemplo do uso de tabelas

public static void main(String[] args) { Application.current().getFrame().setTitle("Exemplo de Tabela"); Dialog dialog = new Dialog(); dialog.setTitle("Exemplo de Tabela"); dialog.setModal(false); dialog.setResizeAllowed(true); dialog.setBounds( 100, 100, 400, 400 ); GridBox table = new GridBox(); table.setVisibleHeader(true); Column firstColumn = new Column(); firstColumn.setName("ID"); table.getColumns().add(firstColumn); Column secondColumn = new Column();GUJ http://www.guj.com.br Pgina 11

Maurcio Linhares de Arago Junior http://maujr.org/

secondColumn.setName("Nome"); table.getColumns().add(secondColumn); Column thirdColumn = new Column(); thirdColumn.setName("Preo"); table.getColumns().add(thirdColumn); for ( int x = 0; x < NOMES.length; x++ ) { Row row = new Row(); row.add( x); row.add( NOMES[x]); row.add( x * 10); table.getRows().add(row);

}

table.setSize(250, 250); dialog.getChildren().add(table); dialog.setVisible(true); }Para criar uma tabela no Thinwire ns precisamos apenas criar o componente GridBox, criar os objetos GridBox.Column, que representam as colunas da tabela e depois popular a tabela com os objetos GridBox.Row, cada objeto Row representa uma linha de informaes na tabela, pra preencher a linha voc deve usar os mtodos add() disponveis no objeto Row. A cada objeto Row que voc adicionar, uma nova linha vai ser mostrada na tabela. A nica configurao alm da normal que ns fazemos na nossa tabela a chamada do mtodo setVisibleHeaders(), que faz com que as colunas sejam mostradas como cabealhos na tabela, se voc no chamar esse mtodo, os cabealhos de coluna no vo ser mostrados na sua tabela, ela j vai comear mostrando os dados da primeira linha que voc criou. O GridBox tambm apresenta outras caractersticas, como a possibilidade de se selecionar as linhas da tabela (e de se registrar para o evento de seleo da tabela). Para saber qual a atual linha selecionada basta chamar o mtodo getSelectedRow(), que retorna a linha que est atualmente selecionada na tabela. Vejamos como registrar um evento que seja chamado na hora que o usurio selecionar uma linha no GridBox: Listagem 8 Exemplo de listener registrado para a seleo de linha

table.addPropertyChangeListener( GridBox.Row.PROPERTY_ROW_SELECTED, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent ev) { Row row = (Row) ev.getSource(); } ); }

Ns registramos o listener no GridBox (o objeto table), mas a propriedade registrada a propriedade do objeto linha, ento o objeto que vai ser enviado como fonte do evento o objeto que representa a linha atualmente selecionda. Imagem 6 Exemplo de tabela

GUJ http://www.guj.com.br Pgina 12

Maurcio Linhares de Arago Junior http://maujr.org/

rvoresMostrar informaes de forma hierrquica utilizando rvores uma necessidade comum e o Thinwire oferece suporte a esse tipo de representao atravs do componente Tree e dos objetos Tree.Item, vejamos um exemplo de uso de rvores para mostrar informaes de forma hierrquica: Listagem 9 rvores no Thinwire

public static void main(String[] args) { Application.current().getFrame().setTitle("Exemplo de rvore"); Dialog dialog = new Dialog(); dialog.setTitle("Exemplo de rvore"); dialog.setModal(false); dialog.setResizeAllowed(true); dialog.setBounds( 200, 200, 400, 400 ); Tree tree = new Tree(); tree.setSize(300,300); tree.setRootItemVisible(false); Item firstItem = new Item(); firstItem.setText("Item 1"); tree.getRootItem().getChildren().add(firstItem); Item secondItem = new Item(); secondItem.setText("Item 2"); tree.getRootItem().getChildren().add(secondItem);GUJ http://www.guj.com.br Pgina 13

Maurcio Linhares de Arago Junior http://maujr.org/

Item thirdItem = new Item(); thirdItem.setText("Item 3"); tree.getRootItem().getChildren().add(thirdItem); Item firstInternalItem = new Item(); firstInternalItem.setText("Internal 1"); firstItem.getChildren().add(firstInternalItem); Item secondInternalItem = new Item(); secondInternalItem.setText("Internal 1"); firstItem.getChildren().add(secondInternalItem); dialog.getChildren().add(tree); dialog.setVisible(true); }Para criar uma rvore, voc primeiro precisa de um objeto rvore, depois voc precisa criar objetos do tipo Tree.Item para representar cada um dos itens da rvore. Se voc deseja que um dos itens tenha sub-itens, basta criar os objetos Tree.Item correspondentes e adicion-los no item que voc deseja que tenha os sub-itens. Imagem 7 Exemplo de rvore

Barras de menuJanelas com barras de menu so uma necessidade comum em aplicaes, para que o usurio possa selecionar facilmente as aes que deseja realizar. O Thinwire define o componente Menu para que essas barras de menu possam ser criadas e apenas os componentes que implementam a interface Window podem receber barras de menu, atualmente, os dois componentes que implementam Window so o componente Frame (que a janela do navegador) e o componente Dialog, que a janela do Thinwire. Vejamos um exemplo do uso de menus no Thinwire: Listagem 10 Exemplo da criao de menus

public static void main(String[] args) { Application.current().getFrame().setTitle("Exemplo de Menu"); Dialog dialog = new Dialog(); dialog.setTitle("Exemplo de Menu"); dialog.setBounds(100, 100, 200, 200); Menu menu = new Menu(); //acessando o item raiz do menuGUJ http://www.guj.com.br Pgina 14

Maurcio Linhares de Arago Junior http://maujr.org/

Item rootItem = menu.getRootItem(); Item fileItem = new Item(); fileItem.setText("Arquivo"); rootItem.getChildren().add(fileItem); Item newFileItem = new Item(); newFileItem.setText("Novo"); fileItem.getChildren().add(newFileItem); Item newProjectItem = new Item(); newProjectItem.setText("Projeto"); newFileItem.getChildren().add(newProjectItem); Item exitFileItem = new Item(); exitFileItem.setText("Sair"); fileItem.getChildren().add(exitFileItem); Item editItem = new Item(); editItem.setText("Editar"); rootItem.getChildren().add(editItem); Item helpItem = new Item(); helpItem.setText("Ajuda"); rootItem.getChildren().add(helpItem); Item openHelpItem = new Item(); openHelpItem.setText("Abrir Ajuda"); helpItem.getChildren().add(openHelpItem); menu.addActionListener(Component.ACTION_CLICK, new ActionListener() { public void actionPerformed(ActionEvent event) { MessageBox.confirm( "Selecionando um item do menu", String.format( "The selected menu item was -> %s", } } ); // Dialogs e Frames implementam a interface Window, //portanto ambos podem ter uma barra de menu dialog.setMenu(menu); dialog.setVisible(true); }Um Menu no Thinwire um componente que tem vrios objetos Menu.Item como seus filhos. Para criar um menu voc precisa primeiro criar um objeto do tipo Menu, acessar a referncia ao Menu.Item raiz desse menu atravs do seu mtodo getRootItem() e depois basta adicionar os itens nesse root item e em seus itens filhos (de forma parecida com a do componente rvore, a diferena aqui que esse item raiz nunca desenhado na tela). Para registrar eventos em um Menu, voc normalmente vai registrar um ActionListener no menu em questo. O objeto que retornado como fonte dos eventos (atravs do mtodo getSource() do objeto ActionEvent) o Menu.Item que foi selecionado pelo usurio, ento no tratamento do evento voc deve implementar uma lgica saiba identificar qual item foi selecionado e o que deve ser feito.GUJ http://www.guj.com.br Pgina 15

event.getSource()));

Maurcio Linhares de Arago Junior http://maujr.org/

Um menu no adicionado a um componente atravs da coleo de filhos (o mtodo getChildren()), ele uma propriedade do objeto no qual vai ser colocado. Menus so sempre colocados atravs do mtodo setMenu() no objeto que voc deseja que o menu aparea. Lembre-se que apenas objetos que implementam a interface Window do Thinwire podem ter barras de menu. Imagem 8 Exemplo de Menu

Fazendo upload de arquivosFazer upload de arquivos em aplicaes web costuma ser um trabalho complicado, com a adio de bibliotecas que no so padro e o uso de objetos que no fazem, necessariamente, parte de uma aplicao web. No Thinwire, toda a lgica de upload de arquivos abstrada do programador, que simplesmente cria o componente e espera que o usurio selecione o arquivo para ser enviado. Vejamos como fazer upload de arquivos com o Thinwire: Listagem 11 Upload de arquivos com o Thinwire

public static void main(String[] args) { Arquivo"); Application.current().getFrame().setTitle("Exemplo de Upload de Dialog dialog = new Dialog("Exemplo de Upload de Arquivo"); dialog.setBounds(0, 0, 400, 400); final FileChooser fileChooser = new FileChooser(); fileChooser.setSize(300, 30); Button uploadButton = new Button(); uploadButton.setText("Enviar Arquivo"); uploadButton.setBounds(0, 40, 100, 30); final Label label = new Label(); label.setBounds(0, 80, 300, 30); uploadButton.addActionListener( Component.ACTION_CLICK , new ActionListener() { public void actionPerformed(ActionEvent event) { FileInfo fileInfo = fileChooser.getFileInfo();GUJ http://www.guj.com.br Pgina 16

Maurcio Linhares de Arago Junior http://maujr.org/

File file = new File(new File(fileInfo.getName()).getName()); System.out.printf("AbsolutePath -> %s%n", file.getAbsolutePath()); try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } fileInfo.saveToFile( file ); label.setText("Salvo em -> " + file.getAbsolutePath()); } }); dialog.getChildren().add(fileChooser); dialog.getChildren().add(uploadButton); dialog.getChildren().add(label); dialog.setVisible(true); }Na nossa interface, ns criamos o componente que faz o upload de arquivos, o FileChooser e criamos mais um boto, que vai ser clicado pelo usurio na hora que ele quiser que o arquivo seja enviado. O componente FileChooser um campo de upload comum de aplicaes web, mas ns no precisamos mais nos preocupar em receber requisies ou fazer qualquer outra coisa, basta esperar que o usurio selecione o arquivo e receb-lo, vejamos como isso acontece: Listagem 12 Tratamento do evento

public void actionPerformed(ActionEvent event) { FileInfo fileInfo = fileChooser.getFileInfo(); File file = new File(new File(fileInfo.getName()).getName()); try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } fileInfo.saveToFile( file ); label.setText("Salvo em -> " + file.getAbsolutePath()); }Ns acessamos a propriede fileInfo do objeto FileChooser, criamos um arquivo onde o contedo que est sendo enviado vai ser gravado e chamamos o mtodo saveToFile() do objeto FileInfo, que vai escrever todo o contedo do arquivo enviado no arquivo que ns criamos. Imagem 8 Upload de arquivos

GUJ http://www.guj.com.br Pgina 17

Maurcio Linhares de Arago Junior http://maujr.org/

Simulando Listas e combos no ThinwireAps mostrar tantos componentes, alguns comuns outros nem tanto, voc deve ter sentido falta de dois componentes que so lugar comum em aplicaes web e desktop, que so as listas de seleo e os combo boxes. No Thinwire, por uma deciso da prpria equipe de desenvolvimento, esses componentes no existem de fato, mas isso no quer dizer que ns no possamos ter componentes que faam o mesmo. Apenas no existem classes, como TextField, que implementam as funcionalidades desses componentes, mas elas podem ser conseguidas com o uso dos componentes padro da biblioteca. Vejamos ento como ns poderamos criar esses componentes: Listagem 13 Exemplo de listas e combos

public static void main(String[] args) { Combos"); Application.current().getFrame().setTitle("Exemplo de Listas e Dialog dialog = new Dialog("Exemplo de Listas e Combos"); dialog.setBounds(200, 200, 600, 400); GridBox listaSelecaoSimples = new GridBox(); listaSelecaoSimples.setVisibleHeader(false); listaSelecaoSimples.setBounds(0, 0, 100, 100); fillGridBox(listaSelecaoSimples); GridBox listaSelecaoMultipla = new GridBox(); listaSelecaoMultipla.setVisibleCheckBoxes(true); listaSelecaoMultipla.setVisibleHeader(false); listaSelecaoMultipla.setFullRowCheckBox(true); listaSelecaoMultipla.setBounds(0, 120, 100, 100); fillGridBox(listaSelecaoMultipla); DropDownGridBox comboBox = new DropDownGridBox(); comboBox.getComponent().setVisibleHeader(false); comboBox.setBounds(0, 240, 100, 30); fillGridBox( comboBox.getComponent() );GUJ http://www.guj.com.br Pgina 18

Maurcio Linhares de Arago Junior http://maujr.org/

dialog.getChildren().add(listaSelecaoSimples); dialog.getChildren().add(listaSelecaoMultipla); dialog.getChildren().add(comboBox); dialog.setVisible(true); }Como voc pde ver pelo cdigo, as listas de seleo nica e mltipla so apenas objetos do tipo GridBox que tem apenas uma coluna e que no mostram os seus cabealhos (a propriedade visibleHeaders est como false). A nica diferena entre a de seleo simples da de seleo mltipla que a de seleo mltipla tem seu estado mantido por um conjunto de checkboxes e no apenas pela seleo da linha do componente. Para saber qual a linha selecionada no de seleo simples, use o mtodo getSelectedRow(), para saber quais as linhas selecionadas no de seleo mltipla, voc deve usar o mtodo getCheckedRows(). O combo box no fim do exemplo apenas um GridBox dentro de um componente DropDown (que um componente que desenha o seu componente filho dentro de uma caixa drop-down) que funciona exatamente da mesma forma que um GridBox comum funcionaria. Imagem 9 Exemplo de listas e combos

Componentes diversosVejamos agora alguns componentes diversos do Thinwire que no tem um uso freqente, mas que podem simplificar tarefas que seriam complexas de se fazer com componentes padro. Vejamos alguns exemplos de uso desses componentes:

Componente ImageO componente Image mostra uma imagem qualquer no lugar onde ele for adicionado. As imagens podem ser de qualquer tipo que o navegador puder aceitar. Listagem 13 Componente Image

public static void main(String[] args) { Application.current().getFrame().setTitle("Exemplo de Imagem"); Dialog dialog = new Dialog(); dialog.setTitle("Janela com Imagem"); dialog.setBounds(100, 100, 400, 400); Image image = new Image("images/logo-guj.gif"); image.setSize(289, 70); dialog.getChildren().add(image);GUJ http://www.guj.com.br Pgina 19

Maurcio Linhares de Arago Junior http://maujr.org/

dialog.setVisible(true); }Parar criar um componente Image, precisamos apenas passar o caminho para a imagem que vai ser mostrada no seu construtor. Os caminhos que podem ser passados so caminhos relativos ao contexto da aplicao (que o caso desse exemplo), o caminho completo no sistema de arquivos ou o caminho dentro do classpath, caminhos dentro do classpath deve ter como prefixo a palavra classpath, como em class:///thinwire.ui.layout.SplitLayout/resources/Image.png. Imagem 9 Exemplo do componente Image

Componente ProgressBarUma ProgressBar (ou barra de progresso) normalmente mede a execuo de alguma tarefa longa ou o tamanho de alguma coisa que tem tendncia a se alterar durante a execuo da aplicao, ela normalmente vai enchendo conforme as aes vo acontecendo. Vejamos um exemplo: Listagem 14 Componente ProgressBar

public static void main(String[] args) { Application.current().getFrame().setTitle("Exemplo de Barra de Progresso"); Dialog dialog = new Dialog(); dialog.setTitle("Janela com Barra de Progresso"); dialog.setBounds(100, 100, 400, 400); final ProgressBar progressBar = new ProgressBar(100, 0); progressBar.setSize(100, 30); Button fillButton = new Button(); fillButton.setText("Preencher"); fillButton.setBounds(0, 40, 50, 30); fillButton.addActionListener(Component.ACTION_CLICK, new ActionListener() { public void actionPerformed(ActionEvent event) { for ( int x = 0; x < 100; x ++ ) { progressBar.setCurrentIndex(x); try {GUJ http://www.guj.com.br Pgina 20

Maurcio Linhares de Arago Junior http://maujr.org/

Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }); Button resetButton = new Button(); resetButton.setText("Zerar"); resetButton.setBounds(60, 40, 50, 30); resetButton.addActionListener(Component.ACTION_CLICK, new ActionListener() { public void actionPerformed(ActionEvent event) { progressBar.setCurrentIndex(0); } }); dialog.getChildren().add(progressBar); dialog.getChildren().add(fillButton); dialog.getChildren().add(resetButton); dialog.setVisible(true); }Nesse exemplo, ns temos uma ProgressBar e dois botes, um que vai enchendo a barra e outro que faz com que o seu contador volte a zero. No construtor da barra ns passamos o seu tamanho e o ndice inicial dela ( o valor no qual ela vai se iniciar), para alterar o valor do seu tamanho, basta alterar a propriedade currentIndex da barra. Imagem 10 Exemplo de ProgressBar

GUJ http://www.guj.com.br Pgina 21

Maurcio Linhares de Arago Junior http://maujr.org/

Componente SliderO componente Slider utilizado para facilitar a seleo de nmeros dentro de um intervalo, como escolher os nmeros entre zero e cem. Vejamos um exemplo de uso do Slider: Listagem 15 Exemplo de Slider

public static void main(String[] args) { Application.current().getFrame().setTitle("Exemplo de Slider"); Dialog dialog = new Dialog(); dialog.setTitle("Janela Slider"); dialog.setBounds(100, 100, 400, 400); final Slider slider = new Slider( 200, 0 ); slider.setSize(100, 30); final TextField textField = new TextField(); textField.setBounds(0, 40, 50, 30); slider.addPropertyChangeListener( RangeComponent.PROPERTY_CURRENT_INDEX , new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { textField.setText( new Integer(slider.getCurrentIndex()).toString() ); } }); dialog.getChildren().add(slider); dialog.getChildren().add(textField); dialog.setVisible(true);GUJ http://www.guj.com.br Pgina 22

Maurcio Linhares de Arago Junior http://maujr.org/

}O Slider funciona com a definio de um intervalo, da mesma forma que o ProgressBar, a diferena que o Slider um componente que o prprio usurio seleciona e diz qual o valor. Imagem 11 Exemplo de Slider

Componente WebBrowserO componente WebBrowser cria um navegador na tela do usurio, permitindo de que da sua aplicao, ele possa abrir outras pginas e at mesmo outras aplicaes. Vejamos um exemplo de seu uso: Listagem 16 Exemplo do componente WebBrowser

public static void main(String[] args) { Application.current().getFrame().setTitle("Exemplo de Navegador"); Dialog dialog = new Dialog("Exemplo de Navegador"); dialog.setBounds(0, 0, 800, 600); WebBrowser webBrowser = new WebBrowser(); webBrowser.setBounds(20, 20, 750, 550); webBrowser.setLocation("http://www.guj.com.br/"); dialog.getChildren().add(webBrowser); dialog.setVisible(true); }Como voc pode ver, basta criar o componente e dizer qual pgina voc deseja que ele carregue, todo o resto do trabalho feito pelo prprio componente. Imagem 12 Exemplo do componente WebBrowser

GUJ http://www.guj.com.br Pgina 23

Maurcio Linhares de Arago Junior http://maujr.org/

RefernciasSite oficial do projeto http://www.thinwire.com/

ConclusoComo voc pde perceber, utilizar o Thinwire para o desenvolvimento de aplicaes web extremamente simples e ainda lhe d como resultado aplicaes com interfaces ricas e responsivas para o seus clientes usando tcnicas AJAX para envio e atualizao d contedo. Entretanto, o Thinwire no a opo correta se voc est buscando desenvolver pginas na web, ele uma boa escolha se a sua necessidade desenvolver aplicaes com interfaces complexas, se o seu problema pode ser resolvido simplesmente com algumas pginas e formulrios, usar outras tecnologias, como Servlets, JSF ou JSP, podem ser uma escolha mais acertada. Tenha em vista tambm que todo o estado da sua aplicao mantida pelo servidor, ento no espere que uma aplicao desenvolvida no Thinwire possa ser instalada num servidor simples e servir a aplicao simultaneamente para milhares de pessoas. Os desenvolvedores do projeto tem clientes que j chegam a at oitocentos usurios simultneos, mas isso extremamente relativo a o tamanho da aplicao e a mquina servidora que est a servindo, ento no pense em fazer uma aplicao dessas rodando em um nico servidor se voc espera ter cinqenta mil pessoas penduradas naquele seu nico servidor. Faa testes de carga e integrao cedo para descobrir se esta realmente a abordagem correta, pra que voc no tenha que esquentar a cabea com problemas de lentido depois que a aplicao tiver sido implantada e comeado a ser utilizada pelo seu cliente.Maurcio Linhares de Arago Junior ([email protected]) graduando em Desenvolvimento de Sistemas para a Internet e Comunicao Social, com Habilitao em Jornalismo, desenvolvedor da Phoebus Tecnologia ( http://www.phoebus.com.br/ ), consultor e instrutor independente, instrutor parceiro da Synapse Tech Cursos ( http://stcursos.com/ ), membro da equipe administrativa do PBJUG ( http://pbjug.org/ ) e colaborador dos fruns do GUJ ( http://guj.com.br/ ).

GUJ http://www.guj.com.br Pgina 24