tag:blogger.com,1999:blog-10302952364170065932024-03-19T02:30:00.885-07:00Aprendendo JavaFXWilliamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.comBlogger68125tag:blogger.com,1999:blog-1030295236417006593.post-42426790724584484682020-11-14T08:39:00.005-08:002020-11-14T08:39:36.158-08:00Criando JARs de aplicações JavaFX<p>O FAT JAR (JAR Gordo) é um tipo de distribuição de aplicações Java onde um único JAR contém todas as dependencias para a aplicação ser executada, necessitando somente de uma máquina virtual Java, uma JVM.</p><p>Para qualquer aplicação Java baseada em maven, criar um FAT JAR poderia ser resolvido usando o plugin <a href="http://maven.apache.org/plugins/maven-shade-plugin/">Maven Shade</a>. No entanto, criar FAT Jars com JavaFX pode ser um desafio, pois JavaFX usa módulos.</p><p>Felizmente esse assunto foi intensamente discutido na internet e uma boa explicação e olução foi proposta pelo Jose Pereda nessa resposta no <a href="https://stackoverflow.com/questions/52653836/maven-shade-javafx-runtime-components-are-missing">StackOverflow</a>.</p><p>Nesse post eu quero brevemente compartilhar os passos para fazer um FAT JAR e postar um exemplo do meu github para que outros possam criar seus próprios JARs baseados nesses exemplo.</p><p><br /></p><h3 style="text-align: left;">Como criar um JAR de uma aplicação JavaFX?</h3><p>1- Crie uma classe com o método main para rodar sua aplicação. Essa classe precisa ter o método main e chamar a sua real aplicação usando o método main dela;</p><p>2- Adicione o plugin shade para o seu projeto. Para quem usar o Gradle notem que o próprio José Pereda postou uma resposta sobre isso no <a href="https://stackoverflow.com/questions/52569724/javafx-11-create-a-jar-file-with-gradle">Stack Overflow</a>;</p><p>3- Na sua configuração do plugin shade certifique-se que você configurou a classe que criou no passo 1.</p><p>Isso é basicamente tudo que você precisa. Se não estiver claro, cheque meu exemplo no <a href="https://github.com/jesuino/fat-jar-javafx">github</a>. Os três arquivos, <b>App.java</b>, <b>Main.java</b> e <b>pom.xml</b> podem ser vistos abaixo.</p><p><br /></p>
<script src="https://gist.github.com/jesuino/226599a4523d9ab8b490090e58a8afbd.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com1tag:blogger.com,1999:blog-1030295236417006593.post-29865661527010581702018-03-06T14:08:00.002-08:002018-03-06T14:08:39.461-08:00Visualizando gráficos de funções matemáticas com JavaFXJá falamos nesse blog sobre os <a href="http://aprendendo-javafx.blogspot.com.br/2014/08/introducao-graficos-com-javafx.html">gráficos da API do JavaFX</a>. Nessa postagem iremos compartilhar uma pequena aplicação que permite plotar qualquer função matemática de N, ou seja, um uso prático dos gráficos. A ideia é ter uma classe que permite você definir funções com nome e um lambda que contém a operação matemática. A aplicação irá de 1 até N (um número que você fornece) executando a função e coletando os dados para colocar no gráfico. O código é muito simples, veja:<br />
<br />
<script src="https://gist.github.com/jesuino/a4e9e98e061a62d42d00de269c1a9e83.js"></script>
<br />
Com esse código podemos plotar, por exemplo, as funções utilizadas em análise de algoritmos, que são:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_NP07eOj6tYlCiP2F6ETPBErNOuydjOvuXCSKy4TQmYcZVWBat1Oe7o9iO88pl_3xOoixII0KaEhB15bsU_VmNRb8mKrOFXF0D_dhpDygObwZnkVldz8bS4tIdmjCxOMCUkfNPHdQDo07/s1600/Screenshot+from+2018-03-06+19-06-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="462" data-original-width="467" height="395" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_NP07eOj6tYlCiP2F6ETPBErNOuydjOvuXCSKy4TQmYcZVWBat1Oe7o9iO88pl_3xOoixII0KaEhB15bsU_VmNRb8mKrOFXF0D_dhpDygObwZnkVldz8bS4tIdmjCxOMCUkfNPHdQDo07/s400/Screenshot+from+2018-03-06+19-06-13.png" width="400" /></a></div>
<br />
<br />
Veja abaixo:<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO2Uc0yuQpAOqb1iONKN_5JWjhm0Na7tZTGQ-Unnx-eNnp_cVoniuYmPYZxALhIe_69g78dKJQPYy091pFtfjdGxeWfpWAlNq64U_7ptBPDBOEijlgTqT5qXS_wWjBRGFEq7yHccvlL3C1/s1600/Screenshot+from+2018-03-06+18-59-53.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="636" data-original-width="1189" height="342" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO2Uc0yuQpAOqb1iONKN_5JWjhm0Na7tZTGQ-Unnx-eNnp_cVoniuYmPYZxALhIe_69g78dKJQPYy091pFtfjdGxeWfpWAlNq64U_7ptBPDBOEijlgTqT5qXS_wWjBRGFEq7yHccvlL3C1/s640/Screenshot+from+2018-03-06+18-59-53.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Podemos selecionar quais funções serão mostradas no momento e ajustar os valores mínimos:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMXjRQ_QnnSDe3LYYm95BOGk2GRQcfadhcOIXceitX5bkxlKsHPEXDy0iCy0bWPgqmUiWQX5R8x4NTyLplN0WTmA_rdT1Rsv6txLCAF5he1bJIbLqa2fPEOA-ODSiAZ8kZe3khiN7_Dvj2/s1600/Screenshot+from+2018-03-06+19-01-31.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="638" data-original-width="1180" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMXjRQ_QnnSDe3LYYm95BOGk2GRQcfadhcOIXceitX5bkxlKsHPEXDy0iCy0bWPgqmUiWQX5R8x4NTyLplN0WTmA_rdT1Rsv6txLCAF5he1bJIbLqa2fPEOA-ODSiAZ8kZe3khiN7_Dvj2/s640/Screenshot+from+2018-03-06+19-01-31.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Para rodar o código você só precisa de Java 8, baixar o arquivo, salvar em PlotarFuncao.java e executar:</div>
<blockquote class="tr_bq">
<br />
$ javac PlotarFuncao.java<br />
$ java PlotarFuncao</blockquote>
<div>
<br /></div>
<div>
Você pode modificar o código e adicionar mais funções. Modifiquei a lista <b>functions</b> para isso:</div>
<div>
<br /></div>
<div>
<div>
<b><span style="white-space: pre;"> </span>static List<NamedFunction> functions = Arrays.asList(</b></div>
<div>
<b><span style="white-space: pre;"> </span>NamedFunction.of("1", n -> 1d),</b></div>
<div>
<b><span style="white-space: pre;"> </span>NamedFunction.of("log n", n -> log2(n)), </b></div>
<div>
<b><span style="white-space: pre;"> </span>NamedFunction.of("n", n -> n),</b></div>
<div>
<b><span style="white-space: pre;"> </span>NamedFunction.of("n log n", n -> n * log2(n)), </b></div>
<div>
<b><span style="white-space: pre;"> </span>NamedFunction.of("n^2", n -> Math.pow(n, 2)),</b></div>
<div>
<b><span style="white-space: pre;"> </span>NamedFunction.of("n^3", n -> Math.pow(n, 3)),</b></div>
<div>
<b><span style="white-space: pre;"> </span>NamedFunction.of("2^n", n -> Math.pow(2, n))</b></div>
<div>
<b><span style="white-space: pre;"> </span>);</b></div>
</div>
<div>
<br /></div>
<div>
Esse post foi mais um <i>rapidinho </i>para compartilhar essa pequena aplicação que, inclusive, já me foi util :-)</div>
<div>
<br /></div>
Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com3tag:blogger.com,1999:blog-1030295236417006593.post-69590606990578220202017-10-27T16:42:00.001-07:002017-10-27T16:42:09.091-07:00JavaFX com Bean Validation e CDI 2.0<span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">Quando JavaFX 2 foi lançado me lembro de muitas pessoas procurando por frameworks que facilitariam a integração de JavaFX com frameworks de validação, um container de injeção de independência e outros serviços enteprise. Atualmente pode integrar JavaFX com Bean Validation e </span><span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">CDI </span><span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">2.0 sem o uso de qualquer framework externo. Nesse artigo eu vou mostrar como validar os campos de sua aplicação JavaFX usando Bean Validation e uma aplicação com CDI.</span><br />
<br />
Antes de falar sobre essas coisas eu recomendo que você cheque os seguintes artigos:<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><br />
<ul style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="border: none; margin: 0px 0px 0.25em; padding: 0px;"><a href="http://fxapps.blogspot.com.br/2017/10/using-cdi-20-in-javafx-application.html" style="color: #6699cc; text-decoration-line: none;">Using CDI 2.0 in a JavaFX application</a></li>
<li style="border: none; margin: 0px 0px 0.25em; padding: 0px;"><a href="http://fxapps.blogspot.com.br/2017/10/testing-bean-validation-20.html" style="color: #6699cc; text-decoration-line: none;">Testing Bean Validation 2.0</a></li>
</ul>
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" />
<h3 style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; margin: 0px; position: relative;">
Validando Controls do JavaFX usando Bean Validation</h3>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<br /></div>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<br /></div>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
Com Bean Validation 2.0 temos o "unwrap" automático de <a href="http://aprendendo-javafx.blogspot.com.br/2014/08/api-do-javafx-properties-listeners-e.html">propriedades JavaFX</a>. Isso significa que se você tiver um campo do tipo ObservableValue o validator vai conseguir tirar o valor real e aplicar a validação. No entanto, os campos de control do JavaFX ainda não são suportados, então se você tentar validar os campos diretamente você vai ter uma exceção: </div>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<br /></div>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWdGM5231825s_YHiylsgygdgETiXoP0zl5_V1VRMEbBPHjs6EPdxNfkbVbs45zjI15iLVZAVP0yB5TFiIoXy2AMqVmHM-7BLecU-pcAeJXp7x3xAjk1z154xTciK1zupA72rT89uFV5M/s1600/Screenshot+from+2017-10-18+01-02-27.png" imageanchor="1" style="color: #6699cc; margin-left: 1em; margin-right: 1em; text-decoration-line: none;"><img border="0" data-original-height="291" data-original-width="754" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWdGM5231825s_YHiylsgygdgETiXoP0zl5_V1VRMEbBPHjs6EPdxNfkbVbs45zjI15iLVZAVP0yB5TFiIoXy2AMqVmHM-7BLecU-pcAeJXp7x3xAjk1z154xTciK1zupA72rT89uFV5M/s640/Screenshot+from+2017-10-18+01-02-27.png" style="border: none; position: relative;" width="640" /></a></div>
</div>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<br />Isso acontece por uqe a implementação do validator não sabe como retirar valores de um controller JavaFX. O que precisamos é criar uma classe que implementa <b>javax.validation.valueextraction.ValueExtractor</b>. Precisamos também usar o tipo do controle que essa classe vai saber tirar o valor (usar genéricos para isso), criar o método que faz a atual extração do valor (tipo um getText em um TextField) e, por fim, usar a anotação <b>javax.validation.valueextraction.ExtractedValue</b> para configurar o tipo que é tirado do control(String, Integer, LocalDate...). Para evitar passos adicionais usamos a anotação <b> javax.validation.valueextraction.UnwrapByDefault</b> na nossa implementação. As nossas classes para tirar valores do DatePicker e do TextField estão abaixo:<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; padding: 4px; position: relative; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-VQSV_a0VBoSc2c6gFcS7139e5O_KZhNAMc8q_e_V_zLyQ3uTHyhzFEjXplZ3FU5HK-i3l9KyK1ymZNC9BH7kOUvSJA_RsXZjoz8TQ4nLo0jBBvu-9GI5dAaGzanEyGSgAcc62fSIWAc/s1600/Screenshot+from+2017-10-18+10-55-26.png" imageanchor="1" style="color: #6699cc; margin-left: auto; margin-right: auto; text-decoration-line: none;"><img border="0" data-original-height="371" data-original-width="1217" height="194" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-VQSV_a0VBoSc2c6gFcS7139e5O_KZhNAMc8q_e_V_zLyQ3uTHyhzFEjXplZ3FU5HK-i3l9KyK1ymZNC9BH7kOUvSJA_RsXZjoz8TQ4nLo0jBBvu-9GI5dAaGzanEyGSgAcc62fSIWAc/s640/Screenshot+from+2017-10-18+10-55-26.png" style="border: none; position: relative;" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 11.88px;">Value Extractor para o DatePicker</td></tr>
</tbody></table>
<br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; padding: 4px; position: relative; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAXIC6e6li4rvYzZ0pW503J0glnVEpk1UgW3Add4CV-r8I8w6PHHofCGJzWF8ouNzLQZKe3fbiMuwoguy0XiifVViZk_yTidOqJLEd7Yvfvv4lLEtpURuO76Zjd6FzIvW7Oh1Cua-YmvQ/s1600/Screenshot+from+2017-10-18+10-55-46.png" imageanchor="1" style="color: #6699cc; margin-left: auto; margin-right: auto; text-decoration-line: none;"><img border="0" data-original-height="331" data-original-width="1173" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAXIC6e6li4rvYzZ0pW503J0glnVEpk1UgW3Add4CV-r8I8w6PHHofCGJzWF8ouNzLQZKe3fbiMuwoguy0XiifVViZk_yTidOqJLEd7Yvfvv4lLEtpURuO76Zjd6FzIvW7Oh1Cua-YmvQ/s640/Screenshot+from+2017-10-18+10-55-46.png" style="border: none; position: relative;" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 11.88px;">Value Extractor para o TextField</td></tr>
</tbody></table>
<br />Finalmente, precisamos registrar isso com o framework de validação. Há </div>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
Finally we must register it in within the bean validation framework. There are a couple of <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-valueextraction-builtinvalueextractors" style="color: #6699cc; text-decoration-line: none;">algumas formas de fazer isso</a>, escolhemos o modo com SPI que é criar um arquivo com o nome <b><i>META-INF/services/javax.validation.valueextraction.ValueExtractor</i></b> com o nome das classes dos nossos ValueExtractors:<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; padding: 4px; position: relative; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9JAjyblb4-NmXt_qyB818qEMCysSL_5MMqzzj2iEyE2M0KWZ_wXszOv38T3bwmKvIYtaTXlejYygGaVPuvQhkkkA-ROCnw4UUmPW_46dw2IwmJOL0lwgt-qPArE2VkW6F8TsP-LZD4OA/s1600/Screenshot+from+2017-10-18+10-57-31.png" imageanchor="1" style="color: #6699cc; margin-left: auto; margin-right: auto; text-decoration-line: none;"><img border="0" data-original-height="89" data-original-width="688" height="82" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9JAjyblb4-NmXt_qyB818qEMCysSL_5MMqzzj2iEyE2M0KWZ_wXszOv38T3bwmKvIYtaTXlejYygGaVPuvQhkkkA-ROCnw4UUmPW_46dw2IwmJOL0lwgt-qPArE2VkW6F8TsP-LZD4OA/s640/Screenshot+from+2017-10-18+10-57-31.png" style="border: none; position: relative;" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 11.88px;">Conteúdo do arquivo <i><b>META-INF/services/javax.validation.valueextraction.ValueExtractor</b></i></td></tr>
</tbody></table>
<br /><br />Poderíamos ter uma extensão de bean validation para os controles do JavaFX, assim não teríamos que criar novamente. Se você sabe de algum projeto assim me fale que eu menciono aqui!<br /><br /><h3 style="margin: 0px; position: relative;">
Mostrar os erros de validation para os usuários</h3>
<br />Você provavelmente quer mostrar os erros para os usuários quando os valores que ele entrou não são válidos. Uma vez que você tenha acesso a classe Validator no controller você simplesmente pode chamar o método validate no controller e mostrar aos usuários os erros de validação em um label, por exemplo. Eu pessoalmente não gosto dessa solução pois eu acho que é muito intrusivo já que você terá que modificar a view para incluir mais labels só para a validação. Uma solução mais simples é mostrar um tooltip com o erro de validação no campo que deu problema. Poderíamos também mostrar um dialog ou bordar o campo de vermelho, mas só mostramos o tooltip mesmo:</div>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; padding: 4px; position: relative; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi34dZKajnQUIVDIGwEGRo9Q6ElprWcSm_LOWRKeNJxupNaChsEtXnpCFqFCaBVYdk0By5XYTtp4Q8_tP4PGog0z1P2GCdDfanj6nw_g0JDerkFrDAHo78QIUZHgnEvLz7danIL8VsYfXc/s1600/Screenshot+from+2017-10-18+11-59-28.png" imageanchor="1" style="color: #6699cc; margin-left: auto; margin-right: auto; text-decoration-line: none;"><img border="0" data-original-height="452" data-original-width="1166" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi34dZKajnQUIVDIGwEGRo9Q6ElprWcSm_LOWRKeNJxupNaChsEtXnpCFqFCaBVYdk0By5XYTtp4Q8_tP4PGog0z1P2GCdDfanj6nw_g0JDerkFrDAHo78QIUZHgnEvLz7danIL8VsYfXc/s640/Screenshot+from+2017-10-18+11-59-28.png" style="border: none; position: relative;" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 11.88px;">Método <b><i>showValidationErrors</i></b> pega o controle que tem erro de validação adiciona um tooltip e mostra</td></tr>
</tbody></table>
<br />Para mostrar o tooltip precisamos acessar o controle em sí e para isso precisamos fazer um pouco de reflexão <strike>por isso fomos ao monte meditar </strike>, por isso o campo usado deve ter o modificador público ou ter métodos de acesso a ele.<br /><br /><h3 style="margin: 0px; position: relative;">
CDI, Bean Validation e JavaFX</h3>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<br /></div>
Não há nada para adicionar sobre CDI aqui do que eu já mencionei no post <a href="http://fxapps.blogspot.com.br/2017/10/using-cdi-20-in-javafx-application.html" style="color: #6699cc; text-decoration-line: none;">Using CDI 2.0 in a JavaFX application</a>. Eu gostaria de compartilhar que CDI e Bean Validation funcionam em uma aplicação JavaFX e por isso eu posso simplesmente injetar o validator na minha classe!Uma única dependência vai tornar isso possível: <i style="font-weight: bold;">org.hibernate.validator:hibernate-validator-cdi. </i>Veja abaixo todos os arquivos da aplicação:<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; padding: 4px; position: relative; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUOQ7YaapXxWtO0zaSrfpcY5BVmsuJszjXzFrEFmcUNGnBVal_FkwfE1RRkvbGx7llFYhIr-wV9tX36dBfUccxQPnVL_Ig-9x4BapKnXcStsB2GK9tBjcTl1JKPuR6UcKdNwN63gov_jc/s1600/Screenshot+from+2017-10-18+12-14-05.png" imageanchor="1" style="color: #6699cc; margin-left: auto; margin-right: auto; text-decoration-line: none;"><img border="0" data-original-height="747" data-original-width="499" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUOQ7YaapXxWtO0zaSrfpcY5BVmsuJszjXzFrEFmcUNGnBVal_FkwfE1RRkvbGx7llFYhIr-wV9tX36dBfUccxQPnVL_Ig-9x4BapKnXcStsB2GK9tBjcTl1JKPuR6UcKdNwN63gov_jc/s400/Screenshot+from+2017-10-18+12-14-05.png" style="border: none; position: relative;" width="266" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 11.88px;">Our maven project and its files</td></tr>
</tbody></table>
<br /><br />Essas são as dependências que eu adicionei ao <b><i>pom.xml</i></b>:<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; padding: 4px; position: relative; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYdGmb5o3R6p9ymIgXOdL36A-yhpCHoMsEdnpYsAvkLW7uv9PQNkwsDKnMtmwAgOgR05cumWF_lhtkSwm3qWXX4Y846ZJn-f6Aj9l3scObM0Vm_RatynzytZjYYua_6XyIG1-xCSePMCo/s1600/Screenshot+from+2017-10-18+12-16-57.png" imageanchor="1" style="color: #6699cc; margin-left: auto; margin-right: auto; text-decoration-line: none;"><img border="0" data-original-height="495" data-original-width="892" height="353" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYdGmb5o3R6p9ymIgXOdL36A-yhpCHoMsEdnpYsAvkLW7uv9PQNkwsDKnMtmwAgOgR05cumWF_lhtkSwm3qWXX4Y846ZJn-f6Aj9l3scObM0Vm_RatynzytZjYYua_6XyIG1-xCSePMCo/s640/Screenshot+from+2017-10-18+12-16-57.png" style="border: none; position: relative;" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 11.88px;">These are all dependencies required to use bean validation and CDI on a JavaFX application</td></tr>
</tbody></table>
<br />O código de uma aplicação de exemplo pode ser encontrado no meu github <a href="https://github.com/AprendendoJava/javafx-basic-tutorials/tree/master/blog-javafx/javafx-cdi2-bean-validation" style="color: #6699cc; text-decoration-line: none;">github</a>. Abaixo você pode ver como a validação usando tooltips funciona na aplicação:<br /><br /><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/biYpX5SWbLg" width="560"></iframe><br /><h3 style="margin: 0px; position: relative;">
<br />Por quey isso é importante?</h3>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<br /></div>
Estar apto a integrar JavaFX com JavaEE (ou devo dizer EE4J já?) é algo chave para quem quer criar aplicação reais com JavaFX, isso trás persistência, validação, injeção de dependência e mais! it will bring persistence, validation, injection and more. A principal questão é: será que isso funcionaria em uma aplicação Android que usa <a href="http://gluonhq.com/products/mobile/javafxports/" style="color: #6699cc; text-decoration-line: none;">Gluon/ JavaFX Ports</a>?</div>
<div style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">
<br />Para mais exemplos de validação você pode ver essa <a href="https://github.com/hibernate/hibernate-demos/pull/24/commits/79b0235a4ce47d785df4f683361ede0985a113d0" style="color: #6699cc; font-size: 14.85px; text-decoration-line: none;">pull request</a> do <a href="https://twitter.com/hendrikEbbers" style="color: #6699cc; text-decoration-line: none;">Hendrik Ebbers</a> para o projeto hibernate validator.</div>
Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-15543986630642440402017-10-25T15:04:00.002-07:002017-10-25T15:04:14.023-07:00Usando CDI 2.0 em uma aplicação JavaFX<span style="background-color: white; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 14.85px;">Com o lançamento do </span><a href="http://www.cdi-spec.org/news/2017/05/15/CDI_2_is_released/" style="background-color: white; color: #6699cc; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-decoration-line: none;">CDI 2.0</a> nós temos um container que pode ser usado em uma aplicação Java SE! Anteriorment se você quisesse fazer uso de CDI em uma aplicação Java SE você teria que usar classes proprietárias do Weld, veja o artigo <a href="https://dzone.com/articles/fxml-javafx-powered-cdi-jboss" style="background-color: white; color: #6699cc; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-decoration-line: none;">FXML & JavaFX—Fueled by CDI & JBoss Weld</a><span style="background-color: white; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif; font-size: 14.85px;">.</span><br />
<br />
Essa feature é bem explicada pelo Adam Bien em um vídeo, veja:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/lyuU24ZFlY4" width="560"></iframe>
<br />
Claro que era meu objetivo tentar isso em uma aplicação javaFX e nesse artigo breve compartilharei com vocês a minha experiência e o código.<br />
<br />
<h3>
Crie o container em uma aplicação JavaFX</h3>
<br />
Uma aplicação JavaFX é uma classe que estende de <b><i>javafx.application.Application</i></b>, que é o ponto de entrada para aplicações JavaFX e onde o stage principal pode ser usado. Para usar CDI devemos criar o SeContainer e certificar-se que ele irá criar todas as classes gerenciadas pelo CDI. Isso deve ser feito no ponto de entrada da Application para que possamos gerenciar todas as classes criadas de lá.<br />
<br />
Uma vez criado o container você tem diferente formas de enviar o Stage para a aplicação JavaFX (a que você vai programar e não a que criamos para grudar CDI ao javaFX). Por exemplo, você pode fazer com que users possam estender uma interface e então injetar a classe do usuário dentro da nossa CDI application para invocar por lá.<br />
<br />
<img height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin2JkzOLNd_vhWN6EoJ6X1NagyFX9jpzuPKFgxUe9n22sU88iOzQIv-ydftnyeluOrsDR5qU9i7w7YR8xNzZrocSiqY5vyajcOFoUOVhJ0shBy902WrkamlPVraQgdVimdoUmsXTbFw1M/s640/Screenshot+from+2017-10-10+20-10-55.png" width="640" /><br />
<br />
Hpa uma forma mais elegante que é usando a API de observer do CDI. Nesse caso podemos criar uma anotação que será o qualifier para o evento javafx.stage.Stage. CDI sabe inteligentemente as classes que observam aquele evento e vai selecionar a classe quando ativarmos o evento com o stage principal. Isso é semelhante ao que você pode ver no artigo que mencionamos FXML & JavaFX—Fueled by CDI & JBoss Weld.<br />
<br />
<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLRuBM_HZfF6C2bAsRdTCLJ6xTUGA_G_ITJZrqxRw1SRvDO2ZP8fCk5IPhETV2PC7hoqehOX_ptNEF9eR3-LwW8BppvkzmFoiok1TNTm33q-iaZxha67W0uvOLBhieFoneL1u6WSSw8PU/s640/Screenshot+from+2017-10-10+20-14-10.png" /><br />
<br />
<span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">Independente da solução que escolher não "desligue o container" ou isso pode deixar app inconsistente. Na verdade isso não deve afetar muito, mas eu decidi não fazer o shutdown.</span><br />
<br />
<span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;"></span>Beleza! Daqui pra frente você pode usar CDI na sua app! Vá em frente e injete coisas nas suas classes JavaFX. Exceto, é claro, se você estiver usando <a href="http://aprendendo-javafx.blogspot.com.br/2014/03/introducao-ao-fxml-criando-interfaces.html">FXML</a>. Nesse caso JavaFX cria os controllers para você usando reflection e CDI não estará ciente da classe criada, ou seja, vai tudo ser nulo pois CDI não injetará. Uma solução é criar um FXMLLoader e fazer o CDI criar os controllers invés de deixar o FXML loader criar ele. O código abaixo foi novamente pego de <span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;"> </span><a href="https://dzone.com/articles/fxml-javafx-powered-cdi-jboss" style="background-color: white; color: #6699cc; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-decoration-line: none;">FXML & JavaFX—Fueled by CDI & JBoss Weld</a><span style="color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif;"><span style="background-color: white; font-size: 14.85px;"> mas com a adição do delicioso lambda do Java 8:</span></span><br />
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9VHO6D3zJry8tRYTEyjkheKAdXinJCWUoRQwbvp2nJzfsMrSCVGQ4WzhrGKkuDGiMhhinuZZd_5moKTRN3VaUXnKqbige3r51SKEEE_HcT1DXHoStKU36f_RMkrJa9KijydumlFMahdg/s1600/Screenshot+from+2017-10-10+20-25-10.png" imageanchor="1" style="background-color: white; color: #6699cc; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; margin-left: 1em; margin-right: 1em; text-align: center; text-decoration-line: none;"><img border="0" data-original-height="230" data-original-width="821" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9VHO6D3zJry8tRYTEyjkheKAdXinJCWUoRQwbvp2nJzfsMrSCVGQ4WzhrGKkuDGiMhhinuZZd_5moKTRN3VaUXnKqbige3r51SKEEE_HcT1DXHoStKU36f_RMkrJa9KijydumlFMahdg/s640/Screenshot+from+2017-10-10+20-25-10.png" style="border: none; position: relative;" width="640" /></a><br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;"><br /></span><br />
<span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">Finalmente você pode criar sua própria aplicação mas NUNCA chame os métodos estáticos do FXMLLoader, use o injetado, por exemplo:</span><br />
<span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;"><br /></span>
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" />
<div class="separator" style="background-color: white; clear: both; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmcxUB_qdDjxRkIKd0fuWbNF5PmlI7wDtbcIClA7yJ5dqc3U0OfN8LKBD5dWIkpMXYeZNm_b6WHUAC74DFHwgKaD5OeENZxkSdCtqyN_127G8cOatRITwL8wrXZcdORs8_YtIFSlc66vU/s1600/Screenshot+from+2017-10-10+20-23-16.png" imageanchor="1" style="color: #6699cc; margin-left: 1em; margin-right: 1em; text-decoration-line: none;"><img border="0" data-original-height="337" data-original-width="839" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmcxUB_qdDjxRkIKd0fuWbNF5PmlI7wDtbcIClA7yJ5dqc3U0OfN8LKBD5dWIkpMXYeZNm_b6WHUAC74DFHwgKaD5OeENZxkSdCtqyN_127G8cOatRITwL8wrXZcdORs8_YtIFSlc66vU/s400/Screenshot+from+2017-10-10+20-23-16.png" style="border: none; position: relative;" width="400" /></a></div>
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">Lembre que você agora pode injetar coisas no seu controller. No nosso caso eu injetei um clássico Greeter, semelhante ao que abordo no post <a href="http://aprendendo-javaee.blogspot.com.br/2012/09/primeiros-passos-com-cdi.html">Primeiros Passos com CDI</a>:</span><br />
<span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;"></span><br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><br />
<div class="separator" style="background-color: white; clear: both; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNsznxS8AFyOJbs_tsOCTHiW8Vls1_N45xRBbpNrvL2rPK8TiX7H1mAh0x2AJySoCtRvUnPYSJNeQM2j5F-0-0ilrrKMs3Xq56HB6JworkxOf6IfborSNYnWRv1KWtIaNPCc15dde5uoE/s1600/Screenshot+from+2017-10-10+12-48-07.png" imageanchor="1" style="color: #6699cc; margin-left: 1em; margin-right: 1em; text-decoration-line: none;"><img border="0" data-original-height="136" data-original-width="452" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNsznxS8AFyOJbs_tsOCTHiW8Vls1_N45xRBbpNrvL2rPK8TiX7H1mAh0x2AJySoCtRvUnPYSJNeQM2j5F-0-0ilrrKMs3Xq56HB6JworkxOf6IfborSNYnWRv1KWtIaNPCc15dde5uoE/s400/Screenshot+from+2017-10-10+12-48-07.png" style="border: none; position: relative;" width="400" /></a></div>
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" />
<div class="separator" style="background-color: white; clear: both; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR8it8dC9Gn3PLRdSAUs5_TKU4rJOkjdNqapWCYwzFC708qex6XqmuxtmhoEorpNneaPXktXrgTuthUeUvxCtZ0PMsGU9yPfxQjs56ucfXQuaNPfT0Et8w8joHjeqZHQ-dI3sKu0GyCXU/s1600/Screenshot+from+2017-10-10+12-48-16.png" imageanchor="1" style="color: #6699cc; margin-left: 1em; margin-right: 1em; text-decoration-line: none;"><img border="0" data-original-height="232" data-original-width="504" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR8it8dC9Gn3PLRdSAUs5_TKU4rJOkjdNqapWCYwzFC708qex6XqmuxtmhoEorpNneaPXktXrgTuthUeUvxCtZ0PMsGU9yPfxQjs56ucfXQuaNPfT0Et8w8joHjeqZHQ-dI3sKu0GyCXU/s400/Screenshot+from+2017-10-10+12-48-16.png" style="border: none; position: relative;" width="400" /></a></div>
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" />
<div class="separator" style="background-color: white; clear: both; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqyKd6GPxY-d6rjNxz97uOAuNoUW38zQ7T1QfQY4OrqdK_7skqSyDncKHB_Jlq37TAYPJRcRS7q8Jsqfy2x2EuP6xA2_0OSaid0NbANrBmrFIiN_famu2pOmCmD0Anttso4n0OUVgN0Hc/s1600/Screenshot+from+2017-10-10+20-29-32.png" imageanchor="1" style="color: #6699cc; margin-left: 1em; margin-right: 1em; text-decoration-line: none;"><img border="0" data-original-height="334" data-original-width="722" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqyKd6GPxY-d6rjNxz97uOAuNoUW38zQ7T1QfQY4OrqdK_7skqSyDncKHB_Jlq37TAYPJRcRS7q8Jsqfy2x2EuP6xA2_0OSaid0NbANrBmrFIiN_famu2pOmCmD0Anttso4n0OUVgN0Hc/s640/Screenshot+from+2017-10-10+20-29-32.png" style="border: none; position: relative;" width="640" /></a></div>
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" />Não se esqueça também do arquivo vazio beans.xml que irá ativar CDI. Essa é a estrutura do projeto que eu usei nos meus testes:<br />
<br style="background-color: white;" /><br />
<div class="separator" style="background-color: white; clear: both; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidFL7qwI8N9mUSw2HwsgS9l9Q173S0qLznGBHKh1Uysbj6IjBd98Dvhx6Ea4MFcgu_8kO5JqeMKmaisUNF3BuQcbl2yge5912pqEu0ZK5CrI652_vyiXBAExJKhnb_PzxLFiUQO467stU/s1600/Screenshot+from+2017-10-10+20-34-39.png" imageanchor="1" style="color: #6699cc; margin-left: 1em; margin-right: 1em; text-decoration-line: none;"><img border="0" data-original-height="575" data-original-width="359" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidFL7qwI8N9mUSw2HwsgS9l9Q173S0qLznGBHKh1Uysbj6IjBd98Dvhx6Ea4MFcgu_8kO5JqeMKmaisUNF3BuQcbl2yge5912pqEu0ZK5CrI652_vyiXBAExJKhnb_PzxLFiUQO467stU/s640/Screenshot+from+2017-10-10+20-34-39.png" style="border: none; position: relative;" width="396" /></a></div>
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><span style="color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif;"><span style="background-color: white; font-size: 14.85px;">O resultado final foi mostrado abaixo - a diferença é que a mensagem veio de um bean gerenciado por FXML:</span></span><br />
<span style="color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif;"><span style="background-color: white; font-size: 14.85px;"><br /></span></span>
<div class="separator" style="background-color: white; clear: both; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEjUpE8FGql4Drcm8eZ5ycPbl_LqzHH7YiF1KKEmhFvX9w-AEpm67NUHnfmCvyLqSpc9ZoGzaWixVWCsb8qOyuqhH8HkxRTJMAzy8sKYCTp9vn4yE-DeorLEVviYnSjrGo5NwrQseiTuA/s1600/Screenshot+from+2017-10-10+20-24-54.png" imageanchor="1" style="color: #6699cc; margin-left: 1em; margin-right: 1em; text-decoration-line: none;"><img border="0" data-original-height="138" data-original-width="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEjUpE8FGql4Drcm8eZ5ycPbl_LqzHH7YiF1KKEmhFvX9w-AEpm67NUHnfmCvyLqSpc9ZoGzaWixVWCsb8qOyuqhH8HkxRTJMAzy8sKYCTp9vn4yE-DeorLEVviYnSjrGo5NwrQseiTuA/s1600/Screenshot+from+2017-10-10+20-24-54.png" style="border: none; position: relative;" /></a></div>
<br style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;" /><span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">O código completo pode ser encontrado no </span><a href="https://github.com/AprendendoJava/javafx-basic-tutorials/tree/master/blog-javafx/javafx-cdi2" style="background-color: white; color: #6699cc; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px; text-decoration-line: none;">github</a><span style="background-color: white; color: #333333; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 14.85px;">.</span><br />
<div>
<br /></div>
Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com2tag:blogger.com,1999:blog-1030295236417006593.post-48937400841746997232017-06-19T18:53:00.001-07:002017-06-19T18:53:50.201-07:00Algoritmo k-means e árvores de decisão com Weka e JavaFX <a href="https://en.wikipedia.org/wiki/Weka_(machine_learning)">Weka</a> é uma das ferramentas mais conhecidas para Machine Learning em Java, que também tem uma ótima API Java que inclui APIs para agrupamento (ou clustering) de dados usando o algoritmo <a href="https://pt.wikipedia.org/wiki/K-means">k-means</a>. Usando JavaFX é possível visualizar dados não-classificados e classsificar os dados usando as APIs usando APIs Weka e então visualizar o resultado em um gráfico JavaFX como o <a href="http://docs.oracle.com/javafx/2/charts/scatter-chart.htm#CIHDEACI">gráfico "scatter"</a>.<br />
<br />
<br />
Nesse post vamos mostrar como uma simples aplicação JavaFX permite você carregar dados, mostrar os dados sem distinção de categoria usando um gráfico, então usaremos weka para classificar os dados usando k-means e finalmnte vamos classificar os dados usando uma árvore de decisão. Usaremos os dados do arquivo <i>iris.2D.arff</i> que vem junto com o download do Weka<br />
<br />
<a href="https://en.wikipedia.org/wiki/K-means_clustering">K-means clustering</a> usando Weka é realmente simples e requer somente algumas linhas de código como você pode ver <a href="http://www.programcreek.com/2014/02/k-means-clustering-in-java/">nesse post</a>. Na nossa applicação iremos construir 3 gráficos para os <a href="https://en.wikipedia.org/wiki/Iris_flower_data_set">dados de flores íris</a>:<br />
<br />
<ol>
<li>Dados sem distinção de classe (sem séries)</li>
<li>Os dados com a classificação real</li>
<li>Dados clusterizados usando Weka</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj43C8l0R8z1w8vTikmxI57vTnC_fqmgh02TBzUyngSh6tqhV19a4j8DgoUXC1GAp72XjMDKb3_c2Obz6Nz3fk015JqQr1pniDMBCzD7eUrPRmr3a0hp8uQLkFDCM7OOcI_6xZgtK7uXAw/s1600/Screenshot+from+2017-06-16+12-07-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="438" data-original-width="1502" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj43C8l0R8z1w8vTikmxI57vTnC_fqmgh02TBzUyngSh6tqhV19a4j8DgoUXC1GAp72XjMDKb3_c2Obz6Nz3fk015JqQr1pniDMBCzD7eUrPRmr3a0hp8uQLkFDCM7OOcI_6xZgtK7uXAw/s640/Screenshot+from+2017-06-16+12-07-13.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Como você pode ver os dados foram agrupados de uma forma que é bem próxima dos dados reais (os dados com valores coletados na vida real). O código para construir os dados agrupados é:</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/jesuino/b033eff359e15836d51329c85988b150.js"></script></div>
<div>
<br /></div>
<div>
Depois de montar esses três gráficos também modifiquei todo o código para adicionar um classificar com <a href="https://en.wikipedia.org/wiki/Decision_tree_learning">árvores de decisão</a> usando a implementação do <a href="http://weka.sourceforge.net/doc.dev/weka/classifiers/trees/J48.html">algoritmo J48</a>. Logo após os gráficos você pode ver a árvore de decisão que montamos a partir dos dados:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHvbcEmTn_DyiBXV-0sOlQe3QDzl86e2JHZ964wvJIAtelkrx1TkRbiLFnHxPPUc5BTbxAO4_MEpsv4l7Vmjll2JPWgS7MZ59qdlU36357s1bGqakBeMJDhIRdQDP8naoWhpxnuBsI-h4/s1600/Screenshot+from+2017-06-16+13-27-27.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="838" data-original-width="1202" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHvbcEmTn_DyiBXV-0sOlQe3QDzl86e2JHZ964wvJIAtelkrx1TkRbiLFnHxPPUc5BTbxAO4_MEpsv4l7Vmjll2JPWgS7MZ59qdlU36357s1bGqakBeMJDhIRdQDP8naoWhpxnuBsI-h4/s400/Screenshot+from+2017-06-16+13-27-27.png" width="400" /></a></div>
<br />
<br />
Quando você clica no gráfico sem classificação você verá que novos dados são adicionados e ele será classificado nos gráficos superiores usando a árvore de decisão e o algoritmo k-means de clustering.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitTds1463YuNoGNSR301C6DoR-TTJ_SuOxBNbadzbZqxDbbHBScKw3OrIbH5XsB88xGkig4J2c65djJ8mpFSB-4yZBiTJmwCYt9VFZKJg4RwqA-dIcbe3b9epsy4y2ZAINDX0a2-m1dHs/s1600/Screenshot+from+2017-06-16+20-54-07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="938" data-original-width="1202" height="311" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitTds1463YuNoGNSR301C6DoR-TTJ_SuOxBNbadzbZqxDbbHBScKw3OrIbH5XsB88xGkig4J2c65djJ8mpFSB-4yZBiTJmwCYt9VFZKJg4RwqA-dIcbe3b9epsy4y2ZAINDX0a2-m1dHs/s400/Screenshot+from+2017-06-16+20-54-07.png" width="400" /></a></div>
<br /></div>
<div>
Nós usamos a árvore de decisão que geramos para classificar os ados e também o cluster. Na imagem acima o cluster classifica alguns dados de forma diferente do que é classificado com a árvore de decisão.<br />
<br />
<script src="https://gist.github.com/jesuino/7605ae86aa73385534315c3d6085a96f.js"></script></div>
<div>
<br />
Eu acho que é particularmente interessante como é fácil visualizar dados com JavaFX. O código completo para esse projeto pode ser encontrado no meu <a href="https://github.com/jesuino/java-ml-projects/tree/master/other-machine-learning/weka-experiments">github</a>, mas aqui está o código da classe principal:</div>
<br />
<br />
<br />
<script src="https://gist.github.com/jesuino/5e20a910d7b4bc0c21d190c506c383d0.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com2tag:blogger.com,1999:blog-1030295236417006593.post-67995959768447378982017-06-13T20:45:00.001-07:002017-06-13T20:45:11.429-07:00Reconhecendo dígitos manuscritos em uma aplicação JavaFX usando DeepLearning4J<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Já falamos sobre<a href="http://fxapps.blogspot.com.br/2017/04/using-tensorflow-from-java-application.html"> tensorflow e JavaFX</a> no blog em inglês, mas a API Java do tensorflow ainda está incompleta. Uma API madura e melhor documentada é o <a href="https://deeplearning4j.org/">DeepLearning4J</a>.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Nesse exemplo nos carregamos o modelo treinado na nossa aplicação, criamos um canvas para desenhar e quando o Enter é pressionado, a imagem do canvas é redimensionada e enviada para o modelo já treinado do deeplearning4j para reconhecimento:</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWxzEmPf0xqqr-agmHDxXgXZWuaaoFkh0wqYMH4oxlPwhOPm34bN1DDPYk_BzCRA1nDFHkpHRqsJjQdQL1G6P6n6JfdrUlC14zvKnuNi68PxgAgTaflbR7EIPRfXXzrpEh_OtITdsn4-8/s1600/Screenshot+from+2017-06-05+22-52-16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="338" data-original-width="522" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWxzEmPf0xqqr-agmHDxXgXZWuaaoFkh0wqYMH4oxlPwhOPm34bN1DDPYk_BzCRA1nDFHkpHRqsJjQdQL1G6P6n6JfdrUlC14zvKnuNi68PxgAgTaflbR7EIPRfXXzrpEh_OtITdsn4-8/s320/Screenshot+from+2017-06-05+22-52-16.png" width="320" /></span></a></div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5o75RtHY8bPPeGgX5XpKc_jvwXQpXOyQeVV25Yf2QbVKD1axDMTY0gt0MJhaobnVNUbzOmHgZxhV29K_x4JflC2hLBnJSH_9Ri5GJsaJ0IGBeM4iiyQBr6FhmJ_llSB9p8R2vwtK5RY0/s1600/Screenshot+from+2017-06-05+23-24-58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="338" data-original-width="522" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5o75RtHY8bPPeGgX5XpKc_jvwXQpXOyQeVV25Yf2QbVKD1axDMTY0gt0MJhaobnVNUbzOmHgZxhV29K_x4JflC2hLBnJSH_9Ri5GJsaJ0IGBeM4iiyQBr6FhmJ_llSB9p8R2vwtK5RY0/s320/Screenshot+from+2017-06-05+23-24-58.png" width="320" /></span></a></div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6ttN9X-fUSDB816ga353a0KPp4PGMgGFilopUnjPFMjbIo7fanTdiyy3p6XBYHI47KLy5yQ5DFVgn73MZTvmjO7fPBZY0Vbj4a6vniB1EkBr6tm5PzJKakyQODwbjofI69OZSJFFArSo/s1600/Screenshot+from+2017-06-05+23-25-29.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" data-original-height="338" data-original-width="522" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6ttN9X-fUSDB816ga353a0KPp4PGMgGFilopUnjPFMjbIo7fanTdiyy3p6XBYHI47KLy5yQ5DFVgn73MZTvmjO7fPBZY0Vbj4a6vniB1EkBr6tm5PzJKakyQODwbjofI69OZSJFFArSo/s320/Screenshot+from+2017-06-05+23-25-29.png" width="320" /></span></a></div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">A forma que isso "advinha digitos é como o "olá mundo" para aprendizado usando redes neurais. Um neurônio imita o neurônio natural do nosso cérebro e ele tem um "peso" que controla quando o neurônio é ativado (no nosso cérebro acontece químicas para ativar um neurônio).Uma rede neural consiste de muitos neurônios conectados uns aos outros e também organizados em camadas. O que temos que fazer é fornecer dados identificados (com labels) para a nossa rede neural e ajustar os pesos dos neurônio até que ela possa "advinhar" resultados para um valor novo que não sabemos. Esse processo é chamado de treinamento.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/BR9h47Jtqyw" width="560"></iframe>
</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Uma vez treinada, nós testamos a rede neural com outros valores também conhecidos para saber a precisão da rede neural (no nosso caso a precisão é 97.5%!). No nosso case usamos o famoso conjunto de dados <a href="http://yann.lecun.com/exdb/mnist/">MNIST</a>.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Pelo motivo de termos camadas ocultas entra a camada de entrada de dados e a camada de saída, nós chamados essas redes neurais de "profundas" (deep neural network) e são usadas no processo de <a href="https://pt.wikipedia.org/wiki/Aprendizagem_profunda">aprendizagem profunda</a>. Nós temos muitos outros conceitos e tipos de redes neurais, eu sugiro você assistis alguns vídeos super interessantes sobre isso no youtube.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/1L0TKZQcUtA" width="560"></iframe>
</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<b><i><span style="font-family: Arial, Helvetica, sans-serif;">E se você estiver ouvindo falar disso pela primeira vez tenha em mente que não será a última!</span></i></b><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Se você tentar o código abaixo vai ver que não é tão preciso quanto essa <a href="http://myselph.de/neuralNet.html">app web</a>, por exemplo. O motivo é que eu não manipulo a imagem precisamente antes de enviar ela para predição, simplesmente redimensionamos ela para ter 28x28 pixels como requerido pelo modelo treinado..</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">O código da aplicação JavaFX é mostrado abaixo e o projeto completo <a href="https://github.com/jesuino/deeplearning-java-projects">está no meu github</a>, including o código usando para treinar nossa rede neural que foi tirado dos <a href="https://deeplearning4j.org/mnist-for-beginners">deeplearning4j examples</a>.</span><br />
<br />
<script src="https://gist.github.com/jesuino/0b201336783f893c89161daa8e785f5e.js"></script>
Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-84987491678942853602017-05-24T09:19:00.001-07:002017-05-24T09:20:00.592-07:00Controlando o Arduino de uma aplicação JavaFXÉ muito empolgante isso! Eu tinha acabado de escrever um <a href="http://aprendendo-javase.blogspot.com.br/2017/05/controlando-o-arduino-partir-do-java.html">pequeno artigo sobre Java e JArduino</a>, mas eu queria fazer um teste com JavaFX e em poucos minutos estava funcionando!<br />
<br />
<h3>
Mostrando informação de um sensor de luz em label</h3>
<br />
No post <a href="http://aprendendo-javase.blogspot.com.br/2017/05/controlando-o-arduino-partir-do-java.html">sobre Java e JArduino</a> nós imprimimos no console a atual intensidade de luz vinda de um sensor LDR conectado a um arduino. Em menos de um minuto conseguimos mostrar essa informação em um label, veja:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7aOGRZYf4TfuFj0ZdnytldCRtZGq3BN58Qxr-3Rb09cKxq_B1jSPTRKLKh-utik8aKRBgAjHW0mwusXpyMJpHYrxGPswSyBlUCTIDXaDmK_GLMA0kR9WDv_8rvjuaeULMZytOAT1eJ-4/s1600/Screenshot+from+2017-04-30+00-29-28.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="88" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7aOGRZYf4TfuFj0ZdnytldCRtZGq3BN58Qxr-3Rb09cKxq_B1jSPTRKLKh-utik8aKRBgAjHW0mwusXpyMJpHYrxGPswSyBlUCTIDXaDmK_GLMA0kR9WDv_8rvjuaeULMZytOAT1eJ-4/s320/Screenshot+from+2017-04-30+00-29-28.png" width="320" /></a></div>
<br />
Eu basicamente reusei a mesma classe do outro post e li a saída em uma thread JavaFX (veja<i><b> Platform.runLater</b></i> no código abaixo).<br />
<br />
<script src="https://gist.github.com/jesuino/78ca9e4f91ab34c8b3bb2b46d8305d94.js"></script>
O plano era também ligar um led da aplicação JavaFX, então vamos seguir o plano original.<br />
<br />
<h3>
Controlando um LED e lendo o LDR</h3>
<br />
Na segunda versão eu usei um gráfico para mostrar os dados do sensor LDR em tempo relam e também um botão para controlar um LED, então quanod ligamos o LED podemos ver o valor do sensor mudando.<br />
<br />
Veja nosso circuito e note um LED no pino digital D1:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmit3RPh87qNifxGkTtgXrz8xAE_YEsBOZYJ0D1n-gvo3NmxEGsAXLC4g7nvrMyqIR9kZvepMwcuV8Q0tBVNQXHc40lfplaTO6A7NIGgsODJn1L3tWclaBtt86OyM38eFS2JU_VJw2WuM/s1600/photo4911725729738237881.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmit3RPh87qNifxGkTtgXrz8xAE_YEsBOZYJ0D1n-gvo3NmxEGsAXLC4g7nvrMyqIR9kZvepMwcuV8Q0tBVNQXHc40lfplaTO6A7NIGgsODJn1L3tWclaBtt86OyM38eFS2JU_VJw2WuM/s320/photo4911725729738237881.jpg" width="320" /></a></div>
<br />
<br />
Agora o código da classe LightSensorApp (que estende de JArduino) foi modificado para incluir um comando de um LED. A App JavaFX ainda é simples, tem um gráfico e um botão:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj56IS5GpFKyG1PZKwL8yJEYB_9eKedNLtmR8RHEe2O4tFpi6U-lhE00iMwHqv2BQ1eUWJQpia9ZI1CUZ_AkKu3TZoHRJJzGLfTUybDLCygBszXUaLovm5LFosJaQ6m5gMYkSh9JWv_7LE/s1600/Screenshot+from+2017-04-30+02-29-02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj56IS5GpFKyG1PZKwL8yJEYB_9eKedNLtmR8RHEe2O4tFpi6U-lhE00iMwHqv2BQ1eUWJQpia9ZI1CUZ_AkKu3TZoHRJJzGLfTUybDLCygBszXUaLovm5LFosJaQ6m5gMYkSh9JWv_7LE/s320/Screenshot+from+2017-04-30+02-29-02.png" width="320" /></a></div>
<br />
<br />
O seguinte vídeo mostra a aplicação em ação:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/XeABU78OydY" width="560"></iframe>
<br />
<br />
O código está mostrado abaixo e não modificamos o pom.xml, somente dois arquivos Java que temos em nosso projeto.<br />
<br />
<script src="https://gist.github.com/jesuino/32840b0b001d90bd0669c33a74aeeddc.js"></script>
<br />
O código usado nesse projeto está no <a href="https://github.com/jesuino/java-arduino">meu github</a>.<br />
<br />
<br />
<br />
<br />Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-15529631423685223952017-01-18T13:19:00.000-08:002017-01-18T13:19:03.045-08:00Física Dinâmica básica em uma aplicação JavaFXSabe o que é bacana? Programar para se divertir. Algumas das melhores formas de se fazer isso é criando jogos, como o Pong, ou brincando com a natureza, como mostra o livro <a href="http://natureofcode.com/">Nature Of Code</a>.<br />
Nessa postagem iremos mostrar os primeiros capítulos desse livro aplicados em um mundo JavaFX. O que iremos mostar:<br />
<br />
<ul>
<li>Gravidade</li>
<li>Aplicando outras forças</li>
</ul>
<div>
<br /></div>
<div>
Claro que o mundo da física e da matemática são muito maiores do que isso, mas espero que a atual aplicação inspire o leitor a criar as suas próprias coisas.</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Sobre a app de teste</h3>
<div>
<br /></div>
<div>
o modelo de nossa aplicação é o já tão conhecido <a href="http://aprendendo-javafx.blogspot.com.br/2014/08/desenhando-livremente-com-canvas-e-o.html">Canvas</a> com uma <i>engine: </i>O Canvas é uma tela de desenho, para desenharmos nele continuamente usamos uma Timeline, o famoso loop.</div>
<div>
<br /></div>
<div>
As coisas desenhadas em um canvas precisam de um X e Y e dentro do loop atualizamos o x e o y de acordo com os acontecimentos e com a entrada do usuário. Para mantermos referëncias aos valores de X e Y, usamos uma classe do JavaFX chamada <b><i><a href="https://docs.oracle.com/javase/8/javafx/api/javafx/geometry/Point2D.html">javafx.geometry.Point2D</a></i></b>.</div>
<div>
<br /></div>
<div>
Tendo isso em mente, vamos entender alguns conceitos usados na nossa aplicação.<br />
<br />
<h3>
Conceitos</h3>
</div>
<div>
<br /></div>
<div>
<b>Vetor: </b>Um vetor na nossa aplicação é uma posicação X e Y, sendo que a direção do vetor dependerá dos sinais X e Y. Na matemática o vetor é um <a href="https://pt.wikipedia.org/wiki/Vetor_(matem%C3%A1tica)">pouco diferente</a>, mas as ideias são semelhantes </div>
<div>
<b>Velocidade: </b>É a variação da posição de um corpo no espaço em um dado período. No nosso código a velocidade se aplica continuamente a posição do corpo na execução do loop da aplicação;</div>
<div>
<b>Aceleração: </b>É a variação da velocidade com o passar do tempo, que, no nosso caso, é determinado também pelo <i>loop;</i></div>
<div>
<b>Massa: </b>É a quantidade de matéria que tem um corpo.</div>
<div>
<br /></div>
<div>
Pois bem, na nossa aplicação o corpo é definido por uma bolinha. Aplicando os conceitos acima, o que temos é uma bolinha parada no meio da tela. Veja:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_AnHn0YYJIXPdNiT1L9aQSD1nT4-k6v5lUQJ3rUGnwbwRLvinJmq090fsrRC2tDfO6jSuM2-3qKqetW6LLHtt6JWzB5NpEydLIHVJXCD0_7uiWHWKPamciNkAEBNBTP-CTPcYsCkJSD3g/s1600/fisica_javafx1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_AnHn0YYJIXPdNiT1L9aQSD1nT4-k6v5lUQJ3rUGnwbwRLvinJmq090fsrRC2tDfO6jSuM2-3qKqetW6LLHtt6JWzB5NpEydLIHVJXCD0_7uiWHWKPamciNkAEBNBTP-CTPcYsCkJSD3g/s320/fisica_javafx1.png" width="320" /></a></div>
<div>
<br /></div>
<div>
Muito sem graça, né? Nada acontece, feijoada, com essa aplicação. O motivo é só um, não há <b>forças</b> aplicadas sobre o corpo. Mas o que é uma força. De acordo com <a href="https://pt.wikipedia.org/wiki/Isaac_Newton">Isaac Newton</a>, força é <i style="font-weight: bold;">qualquer agente externo que modifica o movimento de um corpo livre ou causa deformação num corpo fixo. </i>Não, não estamos falando da força dos Jedi...</div>
<div>
Na verdade, uma força está sendo aplicada sobre o seu corpo nesse exato momento: a <a href="https://pt.wikipedia.org/wiki/Gravidade">Gravidade</a>. A gravidade te puxa para o centro da terra e é por isso que estamos sempre no chão. A nossa bolinha ali em cima está parada, não tem gravidade no <i>mundo dos pixels. </i>E com essa aplicação sem graça, nós já podemos entender a primeira lei de Newton: <i><b>um corpo em repouso permanece em repouso e um corpo em movimento permanece em movimento a menos que sofra efeito de alguma força</b>. </i>Ou seja, essa bolinha está parada aí e é aí que ela vai ficar, exceto se tiver alguma força que faça ela se mover!<br />
Podemos agora modificar nosso programa para mudar isso, podemos aplicar um vetor de gravidade na bolinha. Importante dizer que limitamos a bolinha as bordas da aplicação, assim, toda vez que a bolinha chega nas bordas da tela, simplesmente invertemos a direção do vetor de velocidade.<br />
<br />
O vetor de gravidade "puxa pra baixo", logo, ele precisa ter um X=0 e um Y positivo, vamos colocar 0.1. O resultado é uma bolinha feliz pulando:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtXTpbTvXzQRlouKvyVhqeYVO_f5-A-5I2xSEwbHGqJzUsimMcfWcIX9eaONCQ_M1qeN489otq-EQOHc9wMEosXTXWh7TzWIlwr-RO9dtirqrmGjH5oJZegsdMd3HLgWgCNgmaSyOYwId4/s1600/comGravidade.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtXTpbTvXzQRlouKvyVhqeYVO_f5-A-5I2xSEwbHGqJzUsimMcfWcIX9eaONCQ_M1qeN489otq-EQOHc9wMEosXTXWh7TzWIlwr-RO9dtirqrmGjH5oJZegsdMd3HLgWgCNgmaSyOYwId4/s400/comGravidade.png" width="400" /></a></div>
<br />
<br />
Que bacana, né? Agora vamos colocar outra força: o vento. O vento é uma força simples de se colocar e vamos dizer que o vento bata da esquerda para a direita, precisamos de um vetor que tenha essa direção(X=algum número positivo, Y=0). O resultado é como se segue:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVA14eJvdOJqh3bwnwACjpu2OsJmSYlLUBcYHgkbwes719aBo74hHyYGZ39Y8A9FaVYnRLKfTYUZhVi1oAGaLS5r1ZT_JnYfE8Dq2EMflawdU1Y4pOAJhZn-TbiCjBGwUSRuSmY-UWJwYW/s1600/forcas_com_vento.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVA14eJvdOJqh3bwnwACjpu2OsJmSYlLUBcYHgkbwes719aBo74hHyYGZ39Y8A9FaVYnRLKfTYUZhVi1oAGaLS5r1ZT_JnYfE8Dq2EMflawdU1Y4pOAJhZn-TbiCjBGwUSRuSmY-UWJwYW/s400/forcas_com_vento.png" width="400" /></a></div>
<br />
Note que a bolinha agora fica indo para o canto, bate na "parede" e quando vai voltar, o vento não a deixa!<br />
<br />
Notem que até agora não falamos da massa. Pois bem, a bolinha tem uma massa e de acordo com essa massa, a força é modificada, afinal, se bate um vento no seu quarto algumas coisas leves (um copo de plástico, por exemplo) pode voar, mas não o seu computador e nem você e isso acontece por que as coisas têm massa diferente. Para visualizar isso, colocamos mais 5 bolinhas na tela com massas diferentes. Veja o resultado:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3jK9VGM8grbXtj8UYftbTBAlmIEy8UzK-FypC37f7H43XKhQe8cJVQ9cahuH3b1l0Wf07aCt1wjeQHWGx1axnCmxaD4u6ktOsYA0ESi5F4m6Jew-HQxVKSwnqgnoJboMnec8Qqy3Tq07G/s1600/forcas_varias_bolas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3jK9VGM8grbXtj8UYftbTBAlmIEy8UzK-FypC37f7H43XKhQe8cJVQ9cahuH3b1l0Wf07aCt1wjeQHWGx1axnCmxaD4u6ktOsYA0ESi5F4m6Jew-HQxVKSwnqgnoJboMnec8Qqy3Tq07G/s400/forcas_varias_bolas.png" width="400" /></a></div>
<br />
<br />
A aplicação de forças deve respeitar a <a href="http://mundoeducacao.bol.uol.com.br/fisica/as-leis-newton.htm">segunda lei de Newton</a> que definiu a fórmula que diz que <b>força é igual massa vezes aceleração</b>. Ao aplicarmos a força no código, dividimos ela pela massa e adicionamos à aceleração.<br />
<br />
No vídeo abaixo você vai notar que a velocidade das bolinhas é diferente e isso acontece por causa da massa delas. Como o vento é constante, tudo acaba se movendo, mas isso muda quando adicionamos a força de <a href="https://pt.wikipedia.org/wiki/Fric%C3%A7%C3%A3o_din%C3%A2mica">fricção</a> (atrito, ótima explicação pode ser encontrada <a href="https://www.youtube.com/watch?v=QHxEDkDzcPY">nesse vídeo</a>). A fricção faz com que haja a perda de movimento de acordo com o tempo, logo, o que acontece uns segundos após rodar a aplicação com o adicional da fricção é o seguinte:</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBoumZmP3a3xx2rFMbqh8VzG6hgEcZUDd0z3YbJlbe-nTiR3vxIzbBqafvfYZFmkudygh9HkCRXtfwotW44coI9hDUUAAlcly3W_Un5OKy9Gg2pqz-Htna9E9EWXMnRlpgdlVgsZdWyz9j/s1600/forcas_com_friccao.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBoumZmP3a3xx2rFMbqh8VzG6hgEcZUDd0z3YbJlbe-nTiR3vxIzbBqafvfYZFmkudygh9HkCRXtfwotW44coI9hDUUAAlcly3W_Un5OKy9Gg2pqz-Htna9E9EWXMnRlpgdlVgsZdWyz9j/s400/forcas_com_friccao.png" width="400" /></a></div>
<br /></div>
Vou parar por aqui pois o livro mencionado no início do post tem quase 500 páginas e daria pra continuar aplicando os conceitos em JavaFX até o livro terminar. Veja um pequeno vídeo da aplicação mostrada acima<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/EMxn1N6uMfY" width="560"></iframe>
<h3>
<br /></h3>
<h3>
Conclusão</h3>
<br />
Falamos um pouco sobre física e também programamos. Quem sabe um dia as aulas nas escolas brasileiras não serão assim? Minha missão foi concluída se você está lendo essa linha empolgado e até considerando fazer seus testes localmente. Claro que o que esboçamos é um exemplo muito simples e trata os conceitos de forma muito superficial, mas, mesmo assim, é muito interessante ver isso em ação.<br />
<br />
O código total da aplicação pode ser encontrado <a href="https://github.com/AprendendoJava/javafx-basic-tutorials/tree/master/blog-javafx/fisica-basica-javafx">nosso github</a>.<br />
<br />
<br />Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com1tag:blogger.com,1999:blog-1030295236417006593.post-47556110208027910392017-01-16T19:09:00.004-08:002017-01-16T19:09:43.556-08:00O jogo "Pong" em JavaFX usando 90 linhas de código<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPqjK-qSYzCVJYsvSI3X8FETHDpORCw7sTmTGYQBK9Z5XhiYJvaHCxUoJ0zGEyKrXm0QfktHKKKNE_CSvWXuBE_UJLIk8S7ClWfVeC9PvS4dOSMWsUdfrtlbRCdmekq9Pecb2DSy-eCUTB/s1600/pong.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPqjK-qSYzCVJYsvSI3X8FETHDpORCw7sTmTGYQBK9Z5XhiYJvaHCxUoJ0zGEyKrXm0QfktHKKKNE_CSvWXuBE_UJLIk8S7ClWfVeC9PvS4dOSMWsUdfrtlbRCdmekq9Pecb2DSy-eCUTB/s320/pong.png" width="320" /></a></div>
<br />
<br />
Nesse post eu vou compartilhar uma versão do jogo Pong com vocês que usa somente 90 linhas de código.<br />
<br />
Para executar o jogo, baixe o código abaixo e salve em um arquivo Pong.java e, considerando que você tenha Java 8, rode:<br />
<br />
<b><i> javac Pong.java</i></b><br />
<b><i><br /></i></b>
Compila o código Java<br />
<br />
<b><i>java Pong</i></b><br />
<b><i><br /></i></b>
Roda o jogo.<br />
<br />
O código funciona com o play 1 (o retângulo do lado esquerdo) seguindo o mouse e o outro tentando se posicionar de acordo com a bolinha. Desenhamos o jogo em um canvas e usamos uma timeline como "engine". Quando a bolinha ultrassa os limites laterais da tela, resetamos o jogo e damos o ponto para quem está do outro lado. Quando a bolinha ultrapassa os limites, mas extamente na posição de um dos players, trocamos a sua direção - mesma coisa quando a bolinha ultrapassa o topo ou a parte de baixo.<br />
<br />Veja o código!<br />
<br />
<br />
<script src="https://gist.github.com/jesuino/8f6ccf3e6174502f4e45ad1956172540.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-28071719402462040402017-01-16T05:43:00.002-08:002017-01-16T05:43:10.356-08:00Usando JavaFX para mostrar dados de repasse do governo federalJavaFX é uma ótima plataforma para criar aplicações visuais. Recentemente criamos uma aplicação em JavaFX que permitiu visualizar os repasses do governo federal com facilidade e até uma <a href="https://medium.com/@sjcdigital">postagem sobre isso</a> foi escrita em um blog sobre dados abertos. Com essa aplicação fica muito fácil visualizar os dados de repasse sem ter que vascular o <a href="http://portaldatransparencia.gov.br/">portal da transparência</a>. Veja:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPYwfYGHwMt4GGmaViCiK5rmXQd1Q_401DtZqIbyA0Yo_vvwuRvWXfA-OlMtwO4pQRwY4lW6yyUzGD9eSDs4dWkg3tVx2o_ukbsZ8GF8GG9OBc6OjJ-vGEzyrNLvhBCIc8tKvnIG6gAp17/s1600/repassefx2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="452" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPYwfYGHwMt4GGmaViCiK5rmXQd1Q_401DtZqIbyA0Yo_vvwuRvWXfA-OlMtwO4pQRwY4lW6yyUzGD9eSDs4dWkg3tVx2o_ukbsZ8GF8GG9OBc6OjJ-vGEzyrNLvhBCIc8tKvnIG6gAp17/s640/repassefx2.png" width="640" /></a></div>
<br />
É possível também ver uma pequena animação da evolução dos repasses:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/R2b9ikMviws" width="560"></iframe>
<br />
<br />
O código da aplicação está no <a href="https://github.com/AprendendoJava/javafx-basic-tutorials/tree/master/blog-javafx/visualizacoes/visualize-repasses">meu github</a> e para executa-la primeiro você precisa instalar o <a href="http://aprendendo-javafx.blogspot.com.br/2017/01/desenvolvimento-rapido-de-aplicacoes-de.html">DrawingFX</a> e em seguida você pode importar essa aplicação na sua IDE para executar a mesma (em breve mais melhorias na forma de execução serão feitas).<br />
<br />
<br />
<br />Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-41113150617222596732017-01-13T18:27:00.003-08:002017-01-13T18:27:38.613-08:00Algoritmo Genético e um exemplo com JavaFX<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqLWbyCNeVWdyFzBZJfeKFGpQhE2PSIii3CVUMz6oMKtc-1Fzb8eLL79BJlIkmbHkvQ_hr7VEfDYroSs2i7ElcFj7YI887_L3duET9O-1gDMTyOzsqg8SgPdg-hBOftdyCFxQhAF3Gk1WG/s1600/mazefx.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqLWbyCNeVWdyFzBZJfeKFGpQhE2PSIii3CVUMz6oMKtc-1Fzb8eLL79BJlIkmbHkvQ_hr7VEfDYroSs2i7ElcFj7YI887_L3duET9O-1gDMTyOzsqg8SgPdg-hBOftdyCFxQhAF3Gk1WG/s400/mazefx.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Saindo do labirinto usando algoritmo genético</td></tr>
</tbody></table>
<br />
<br />
<div style="text-align: center;">
<i><a href="http://fxapps.blogspot.com.br/2017/01/escape-javafx-maze-using-genetic.html">Esse post é uma união de pois posts no meu blog em inglês</a></i></div>
<br />
<br />
Um dos tópicos mais fascinantes no mundo da ciência da computação é <b>Inteligência Artificial (IA)</b>. Uma sub-divisão no mundo da inteligência artificial são aqueles algoritmos que são baseados na natureza e nesse grupo temos os Algoritmos Genéticos.<br />
<br />
<br />
<h3>
Algoritmos Genéticos</h3>
<br />
<br />
Eu não irei me aprofundar nesse tópico, mas há ótimos materiais na internet. A ideia geral é um algoritmo que leve em conta, dado um indíviduo, ele:<br />
<br />
<ul>
<li>Tenha variação genética em diversos indivíduos (organismos também se aplica aqui);</li>
<li>Possa se reprodução e levar o código genético para suas gerações;</li>
<li>A cada reprodução haja ligeiras variações genéticas;</li>
<li>Uma "nota" para saber quão aquele indíviduo está adaptado ao ambiente atual.</li>
</ul>
<br />
Isso tudo é parte da teoria mais que comprovada de Darwin. O nome "teoria" confunde algumas pessoas e isso é incrível, acham que por ser uma teoria, é algo não confiável, mas interessantemente todas as evidências validam essa teoria desde que ela foi publicada! Sobre IA e Evolução, Pirulla fala um pouco disso no vídeo abaixo.<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/2v3DyAAlH4E" width="560"></iframe>
<br />
<br />
Para saber mais sugiro a <a href="https://pt.wikipedia.org/wiki/Algoritmo_gen%C3%A9tico">página da Wikipédia</a> sobre o assunto e o vídeo de uma aula do MIT e, de novo, um vídeo do Shiffman.<br />
<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/kHyNqSnzP8Y" width="560"></iframe>
<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/9zfeTw-uFCw?list=PLRqwX-V7Uu6bJM3VgzjNV5YxVxUwzALHV" width="560"></iframe><br />
<br />
<br />
<h3>
Algoritmos genéticos usando Java</h3>
<br />
Para colocar isso em prática usando em Java você pode desenvolver o seu próprio mini framework com DNA, Genes, cromossomos, algoritmos de mutação ou cruzamento e algoritmos de seleção natural, mas pra que reinventar a roda? No mundo Java temos algumas bibliotecas já conhecidas nesse meio, destaco a JGAP, um pouco antiga, e a moderna Jenetics, que usa Java 8 e os novos conceitos como Lambda, Method Reference, Stream, etc. O guia do usuário da API Jenetics é muito bom, cobre quase todas as classes que são usadas durante a programação. Mas ainda senti falta de exemplos mais claros, por isso, antes de tentar algo visual com JavaFX, eu criei 3 pequenas aplicações.<br />
<br />
<br />
<b>Seleciona o conjunto de double que tem a maior soma de algarismos;</b> Esse é um exemplo besta, mas que mostra algumas classes importantes da API. A ideia é: dado um conjunto de double, qual tem a maior soma dos algarismos? Veja o código.<br />
CODE<br />
<br />
A saída é algo assim:<br />
<br />
<b><i>[[[85],[23],[62]]], sum 26</i></b><br />
<b><i>[[[42],[5],[53]]], sum 19</i></b><br />
<b><i>[[[4],[82],[14]]], sum 19</i></b><br />
<b><i>[[[17],[99],[41]]], sum 31</i></b><br />
<b><i>[[[32],[16],[23]]], sum 17</i></b><br />
<b><i>[[[15],[85],[38]]], sum 30</i></b><br />
<b><i>[[[54],[30],[51]]], sum 18</i></b><br />
<b><i>[[[31],[20],[76]]], sum 19</i></b><br />
<b><i>[[[88],[63],[69]]], sum 40</i></b><br />
<b><i>[[[52],[11],[6]]], sum 15</i></b><br />
<b><i> (Um monte de passo intermediário)</i></b><br />
<b><i>[[[88],[97],[97]]], sum 48</i></b><br />
<b><i>[[[88],[97],[97]]], sum 48</i></b><br />
<b><i>[[[88],[29],[25]]], sum 34</i></b><br />
<b><i>[[[88],[97],[95]]], sum 46</i></b><br />
<b><i>[[[88],[97],[97]]], sum 48</i></b><br />
<b><i>Selected: [[[88],[97],[97]]]. Sum: 48</i></b><br />
<div>
<br /></div>
<br />
Veja que podemos resolver ele ser usar algoritmo genético, mas no código acima você pode começar a entender a pegada da API: Cromossomos tem um conjunto de genes, os genes são os objetos reais da sua aplicação (um número, uma String, um objeto do tipo pessoa...), genotype é o conjunto de cromossomos e criamos dois métodos importantes: um gera valores para serem trabalhados pela API (no exemplo acima usamos um cromossomo da própria API e ele tem o método pra gerar: <b><i>Genotype.of(LongChromosome.of(1, 100, 3));</i></b>) e o método que recebe o Genotype para que você possa trabalhar nele e retornar um ranking ou um número que indica quanto aquele genotype está adaptado ao ambiente (ver o método <i>fitness</i>).<br />
<br />
<script src="https://gist.github.com/jesuino/c0f4b7aab2a3f1f4d9528a1b3c722eaf.js"></script>
<br />
<b>Escrevendo uma frase: </b>Se você conseguir 1 milhão de macacos e falar pra eles darem tapas no teclado de 1 milhão de computadores, qual seria a chance desse texto sair uma música da banda Queen? Raras, muito raras. Um programa com algoritmo genético pode chegar a esse resultado muito mais rápido e é claro que esse é somente outro exemplo. Veja abaixo um programa com Jenetics que consegue escrever uma frase que você escrever usando evolução:<br />
<br />
<br />
<script src="https://gist.github.com/jesuino/bc789570bff8f5d3051d8487de8d0def.js"></script>
<br />
<br />
<b>Escape do Labirinto: </b>Esse é um exemplo um pouco mais elaborado. Nele temos um pequeno labirinto gerado e a função do algoritmo genético é evoluir o conjunto inicial de direções do labirinto para encontrar uma saída. Bem, esse código é um pouco extenso, assim peço para vocês verem no meu <a href="https://github.com/jesuino/genetics-algorithm-tests">github</a>. A ideia é ter genes que são customizados, do tipo <i style="font-weight: bold;">Direction </i> e esses genes são uma possível saída para o labirinto, representado pela classe Maze. Incrivelmente, com algoritmo genético, as direções iniciais são mutadas de forma que conseguem encontrar uma saída do labirinto! Vejam uma tela:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEQVCY5F49aSLwxr83gQzToIZ8ieBcBw0s2COc9qqztA9IQlqt0g3MyUQRl0vd1EI6k5fxOKBmP77vzsvqY49wyl856f4CulkZOFlQ4tME6CCqS9mVfNQDV4jiqpmmL1DY0wrnGWw-LF4K/s1600/maze.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEQVCY5F49aSLwxr83gQzToIZ8ieBcBw0s2COc9qqztA9IQlqt0g3MyUQRl0vd1EI6k5fxOKBmP77vzsvqY49wyl856f4CulkZOFlQ4tME6CCqS9mVfNQDV4jiqpmmL1DY0wrnGWw-LF4K/s320/maze.png" width="194" /></a></div>
<br />
<br />
Como esse é um blog sobre JavaFX, foi criada uma aplicação que desenha o labirinto e permite que você teste parâmetros para rodar o algoritmo! O código dele também é extenso e ninguém vai ler um blog com dezenas de linhas de código! Então, caso queiram estudar mais, aqui vão os passos para executar a aplicação (precisa de Maven e Java 8):<br />
<br />
<br />
<ul>
<li>Primeiro instalem o DrawingFX que já falei sobre ele aqui: <a href="http://aprendendo-javafx.blogspot.com.br/2017/01/desenvolvimento-rapido-de-aplicacoes-de.html">http://aprendendo-javafx.blogspot.com.br/2017/01/desenvolvimento-rapido-de-aplicacoes-de.html</a></li>
<li>Clone o repositorio <a href="https://github.com/jesuino/drawing-fx">https://github.com/jesuino/drawing-fx</a> (ou baixe o código), entre no diretório criado com o código e rode: <i>mvn clean install</i></li>
<li>Agora clone o repositório onde está todo o código do labirinto: <a href="https://github.com/jesuino/genetics-algorithm-tests">https://github.com/jesuino/genetics-algorithm-tests</a></li>
<li>Por fim, entre no diretório com o código e rode:</li>
</ul>
<b><i>$ mvn clean package exec:java -Dexec.mainClass=org.fxapps.genetics.mazefx.MazeFXApp</i></b><br />
<b><i><br /></i></b>
O resultado pode ser visto no vídeo abaixo:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/pTcZI6C9sF0" width="560"></iframe>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com1tag:blogger.com,1999:blog-1030295236417006593.post-47837309130712158222017-01-10T13:18:00.002-08:002017-01-10T13:18:08.802-08:00Simples Relógio com JavaFXO participante Welington Pietronero, do grupo <a href="https://groups.google.com/forum/#!forum/javafx-br">JavaFX-BR</a>, pediu um exemplo de um label que mostra as horas com JavaFX. Criamos um simples relógio:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zsOa-DUMmpzOzXU_iSO4fgniLPeGqlOpOttBMlglExyLXwebLFQK-OVZnlUXbNRBcgm6UhHoC9rj5pfhjxsnLWQBveVv5JJmsosBPEOgO5mzCan_wpPPP7yY2ZNi7wHlWSSc1dE6qhO1/s1600/relogio.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zsOa-DUMmpzOzXU_iSO4fgniLPeGqlOpOttBMlglExyLXwebLFQK-OVZnlUXbNRBcgm6UhHoC9rj5pfhjxsnLWQBveVv5JJmsosBPEOgO5mzCan_wpPPP7yY2ZNi7wHlWSSc1dE6qhO1/s400/relogio.png" width="400" /></a></div>
<br />
A criação foi bem simples, segue aqui uma explicação rápida do código e em seguida o próprio código:<br />
<br />
<br />
<ul>
<li>O texto vai ficar em um Label, no programa chamamos ele de lblRelogio;</li>
<li>Para transformar o objeto data em texto, precisamos de um <a href="http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html">SimpleDateFormat</a>. Essa é uma classe bem bacana e ao criarmos uma instância da mesma, passamos uma String que representará a forma que a hora/data será representada. Há uma tabela na <a href="http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html">documentação dessa classe</a> que mostra como podemos formatar a nossa data, no nosso caso usamos: <b><i>hh:mm:ss a</i></b> - que resulta no formato mostrado acima. Claro que há uma nova API de datas no Java 8, mas a API antiga ainda é muito usada!</li>
<li>No método start (se não entende o que faz esse método, por favor, veja <a href="http://aprendendo-javafx.blogspot.com.br/2012/07/sua-primeira-aplicacao-em-javafx-usando.html">esse post</a>) criamos uma <a href="https://docs.oracle.com/javafx/2/api/javafx/scene/text/Font.html">Font</a> para o lblRelogio. Essa fonte aceita parâmetros que definem se a fonte ficará em negrito ou alguma variação de negrito ou se a fonte vai ficar em itálico ou normal. Lembrando que é possível usar <a href="http://aprendendo-javafx.blogspot.com.br/2014/07/adicionando-estilo-sua-aplicacao-com-css.html">CSS</a> também;</li>
<li>Por fim, a chave do nosso código é a Timeline, que executa os KeyFrames no tempo passado como parâmetro. Um KeyFrame terá uma ação associada a ele e no nosso caso simplesmente chamamos o método atualizaHoras. A timeline executará "eternamente" o KeyFrame a cada 1 segundo.</li>
</ul>
<div>
Veja o codigo!</div>
<div>
<br /></div>
<script src="https://gist.github.com/jesuino/38880f517c0bdb3551c5a4d93a6fb038.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com3tag:blogger.com,1999:blog-1030295236417006593.post-52027333732281463572017-01-08T14:38:00.002-08:002017-01-08T14:38:24.735-08:00Super Formas com JavaFX<br />
Mais uma postagem sobre efeitos visuais com JavaFX e hoje vamos falar sobre a aplicação da <a href="https://en.wikipedia.org/wiki/Superformula">Superformula</a>, derivada da fórmula <a href="https://en.wikipedia.org/wiki/Superellipse">Superellipse</a> para gerar <a href="http://paulbourke.net/geometry/supershape/">supershapes</a>! Pode parecer confuso, mas vamos aplicar uma fórmula no JavaFX e gerar formas geométricas bacanas somente trocando os parâmetros da fórmula!<br />
Claro a inspiração novamente veio do Shiffman! Veja abaixo o vídeo dele:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/ksRoh-10lak?list=PLRqwX-V7Uu6ZiZxtDDRCi6uhfTH4FilpH" width="560"></iframe>
<br />
O código principal foi tirado do <a href="http://paulbourke.net/geometry/supershape/">artigo do Paulo Bourke</a> aplicando o algoritmo em um ângulo 0 até 2*PI temos diversas formas geradas.<br />
<br />
O código é bem simples! Novamente usamos aquela classe utilitária para desenhar em JavaFX e a cada ciclo nós vamos aplicar a fórmula com novos parâmetros e então transformamos os resultados em pontos X e Y e desenhamos na tela pontinhos. O número de pontos define a resolução e para gerar todos os pontos fazemos um loop e pegamos um ângulo baseado no ponto atual do loop, aplicamos a fórmula e pegamos os pontos.<br />
<br />
Em outras palavras, se quisermos 10 pontos, aplicamos a fórmula usando (0 * 10 / PI *2), (1 * 10 / PI *2), , (2 * 10 / PI *2), (1 * 10 / PI *2) e assim vai...<br />
<br />
Mas o ponto principal são as constantes. Ao executar a fórmula, podemos mudar algumas constantes e como resultado temos formas geométricas completamente diferentes! As constantes são m, n1, n2 e n3!<br />
<br />
A nossa aplicação muda os valores das "constantes" e aplica a fórmula a cada frame executado. O resultado é o seguinte:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXGqXUQZeCEkp9TGpGZ3bSpNxVl60_0vuWo5SrQVFnTe2sNn5E8Xyw1nQlwCUCgjz-RB-GpQku1q0b2Ur59IG5_FFZsbApr-2V_u5rO93GPhVZMJFcl6M_TMOM8HOnSmXlmxqfrxftaeer/s1600/supershapes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXGqXUQZeCEkp9TGpGZ3bSpNxVl60_0vuWo5SrQVFnTe2sNn5E8Xyw1nQlwCUCgjz-RB-GpQku1q0b2Ur59IG5_FFZsbApr-2V_u5rO93GPhVZMJFcl6M_TMOM8HOnSmXlmxqfrxftaeer/s640/supershapes.png" width="640" /></a></div>
<br />
Os tipos de azul utilizados foram escolhidos pela minha amada Luana e o código da aplicação ficou bem compacto, pode ver abaixo:<br />
<br />
<br />
<br />
<h3 style="text-align: center;">
<a href="https://github.com/AprendendoJava/javafx-basic-tutorials/tree/master/blog-javafx/visualizacoes/superformas-javafx">Projeto completo no github</a></h3>
<script src="https://gist.github.com/jesuino/9c79f5c69e72e6292993ddc1a5097194.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-17815690164810901502017-01-07T13:04:00.003-08:002017-01-07T13:04:41.774-08:00Desenvolvimento rápido de aplicações de efeitos visuais com JavaFXQuem acompanha o blog notou que ultimamente temos postado somente aplicações mais visuais sempre se baseando nos <a href="https://www.youtube.com/channel/UCvjgXvBlbQiydffZU7m1_aw">vídeos do mestre Daniel Shiffman</a>. Pois bem, ele usa Processing, uma outra linguagem de programação e esse é um blog sobre JavaFX e o nosso objetivo é também sempre se manter em contato com Java - em outras palavras, quero "levar a palavra" do Shiffman para o mundo e ainda exercitar Java. A palavra de Shiffman é a seguinte:<br />
<br />
<i>"Processing, for me, has always been just the most wonderful thing ever. It’s given me a mission and a passion, to bring computation to everyone: artists, designers, musicians, biologists, doctors, dancers, animators, bankers, photographers, librarians, fashion designers, architects, psychologists, journalists, and writers, just to name a few. Writing code can be scary, something many mistakenly think is reserved for computer scientists and engineers. Processing has helped eliminate that fear, making programming accessible to a wider audience, particularly artists.”</i><br />
<i><br /></i>
Fonte: <a href="https://en.wikipedia.org/wiki/Daniel_Shiffman">Wikipedia</a><br />
<br />
Ou seja, ele encontrou em processing uma forma de levar programação a mais pessoas. Com JavaFX não é diferente, é possível programar e criar aplicações sem ser um mestre Java - mas, a linguagem ainda aparece as vezes como um empecilho. Eu escrevo esse blog há 4 anos e estou "mexendo" com JavaFX desde a primeira versão, uns 8 anos já e vejo isso acontecendo.<br />
Mas por que o blog então não é sobre Processing? O motivo é que Java é super importante para o mercado e "brincando" com JavaFX você exercita Java também, mas é necessário o equilibrio para que a linguagem Java não seja um empecilho.<br />
<br />
Resumindo, criei uma classe que estou usando em aplicações visuais que "imita" o processing - mas é claro que o Processing é um universo a parte, a ideia é tirar partes repetitivas para que se tenha o foco na aplicação visual. O nome da classe é "DrawingApp", como já visto no <a href="http://aprendendo-javafx.blogspot.com.br/2017/01/flores-com-javafx.html">post sobre as flores</a> e no post sobre o <a href="http://aprendendo-javafx.blogspot.com.br/2017/01/efeito-metaballs-com-javafx.html">algoritmo Metaballs</a>.<br />
Veja abaixo o exemplo de uma aplicação simples (bolas coloridas) que usa a DrawingApp e o código da classe DrawingApp.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimFzBST3Ch-WE1-o6AHbg7fw7lfqYs7Qp9w6SuFwSWsfWKnTUWHuqeSJSdL_fZESo1ipnAVyFN70XeSc5uJ9Q-m1R6g5AJXg0_QuC3yiqwndrGBNgysEdr938UldIgMHlgrtnIiHal2cOO/s1600/bouncingBalls.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimFzBST3Ch-WE1-o6AHbg7fw7lfqYs7Qp9w6SuFwSWsfWKnTUWHuqeSJSdL_fZESo1ipnAVyFN70XeSc5uJ9Q-m1R6g5AJXg0_QuC3yiqwndrGBNgysEdr938UldIgMHlgrtnIiHal2cOO/s320/bouncingBalls.png" width="320" /></a></div>
<br />
<script src="https://gist.github.com/jesuino/6c238615234049b62cc15ad2e7fc6be6.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-3347766080185844852017-01-06T18:26:00.001-08:002017-01-06T18:31:56.885-08:00Flores com JavaFXTodo mundo sabe que a natureza pode ser representada matematicamente e muitas das fórmulas da natureza são conhecidas. O maior exemplo é a <a href="http://planetabiologia.com/a-sequencia-de-fibonacci-na-natureza/">sequência de Fibonacci</a> e como pode ser encontrada na natureza:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxuWgf38Moo3ItRJfmKbRWHYJeHlyYUg6Vce_qbQaAv69dHYTnGucyMgw2jEO5oGg5vC5njZu-0ZRFlhJs4nd7YMlj7slJkbfONSiQ3EqWbGEOSEmz6zddDy8fZKLsqNLgSWaM0mKKnruS/s1600/fib1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxuWgf38Moo3ItRJfmKbRWHYJeHlyYUg6Vce_qbQaAv69dHYTnGucyMgw2jEO5oGg5vC5njZu-0ZRFlhJs4nd7YMlj7slJkbfONSiQ3EqWbGEOSEmz6zddDy8fZKLsqNLgSWaM0mKKnruS/s320/fib1.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR1wASYO1Q9ZYitZj7zj4y6jaNmiN5Nflgh2HFO11aPpWjYFKBImnBzwRBFfPBqXHvHFq2NzvJAKQ-ZXZWJRSlYS14JLj_M8pizhx5R0AHfvQ4Ls6_aOMLtr1Y4KLp0MhHsvdRmKmhccGn/s1600/fib2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR1wASYO1Q9ZYitZj7zj4y6jaNmiN5Nflgh2HFO11aPpWjYFKBImnBzwRBFfPBqXHvHFq2NzvJAKQ-ZXZWJRSlYS14JLj_M8pizhx5R0AHfvQ4Ls6_aOMLtr1Y4KLp0MhHsvdRmKmhccGn/s320/fib2.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1qjCQai0rmxdvqC9nZl9sAisHSOiZ8_Ybki3t0-eLU2oAm0KJwQgsWyG1bOTht96LChpXeRsWsW-FE9guxqAaDrYqrX65jr_DwnPkw6Y-xnOpP47rJ04S-9Lj0JrmlmQvjqGgd6FucHtC/s1600/fib3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1qjCQai0rmxdvqC9nZl9sAisHSOiZ8_Ybki3t0-eLU2oAm0KJwQgsWyG1bOTht96LChpXeRsWsW-FE9guxqAaDrYqrX65jr_DwnPkw6Y-xnOpP47rJ04S-9Lj0JrmlmQvjqGgd6FucHtC/s320/fib3.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Pois bem, hoje vamos usar mais uma <a href="http://mathworld.wolfram.com/Phyllotaxis.html">fórmula muito interessante</a> que tomei conhecimento de mais um vídeo do mestre Shiffman, veja:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/KWoJgHFYWxY" width="560"></iframe>
<br />
<br />
Filotaxia é o nome em português dessa área de estudo e você pode ler mais sobre ela na <a href="https://pt.wikipedia.org/wiki/Filotaxia">wikipédia</a>. No <a href="http://mathworld.wolfram.com/Phyllotaxis.html">Phyllotaxis</a> você pode ter acesso a um documento e ao algoritmo que o Shiffman e eu usamos.<br />
Mais uma vez usamos o canvas em uma aplicação que vai criar "plantas" aleatóriamente na tela. Para isso, ao contrário do que fez o Shiffman, vamos criar uma classe que vai desenhar a nossa plantinha.<br />
<br />
Mas como funciona o algoritmo? A ideia é muito simples, temos um ângulo mágico e aplicamos uma fórmula sobre ele usando um número que é incrementado a cada frame de uma animação, por fim, aplicamos trigonometria para conseguir os pontos X e Y que iremos desenhar na tela. Em seguida, desenhamos os pontos gerados.<br />
A ideia geral é essa! Usamos uma classe genérica com os elementos que <a href="http://aprendendo-javafx.blogspot.com.br/2017/01/efeito-metaballs-com-javafx.html">mostramos no post anterior</a> e o código ficou bastante limpo. Em breve falo sobre o DrawingFX...<br />
Veja em seguida um screenshot da aplicação, o código, e um vídeo onde eu mostro partes do código e executo a aplicação.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim4nWVPp7yBSdKiehsBtBzlx_xmG5u_eAyYYS9nBLDPJtAEar7Vrnewn1AZeGPZzvlFJsQ7EIg0FyS9-zvxaiAjCbMj_ZDMXcCt-UJmX1nMZieX6FogO4d4QRPnhq4NyHwWhGSe_zNt5-w/s1600/Screenshot-Flowers+App-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim4nWVPp7yBSdKiehsBtBzlx_xmG5u_eAyYYS9nBLDPJtAEar7Vrnewn1AZeGPZzvlFJsQ7EIg0FyS9-zvxaiAjCbMj_ZDMXcCt-UJmX1nMZieX6FogO4d4QRPnhq4NyHwWhGSe_zNt5-w/s400/Screenshot-Flowers+App-2.png" width="400" /></a></div>
<br />
<br />
<script src="https://gist.github.com/jesuino/778926d157781a985e98e95cb8036abf.js"></script>
<br />
<br />
<br />
Por fim vejam esse vídeo rápido que fiz para demonstar a APP e falar um pouco do código.<br />
<br />
<iframe width="560" height="315" src="https://www.youtube.com/embed/RcMIvYtA2W4" frameborder="0" allowfullscreen></iframe>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com1tag:blogger.com,1999:blog-1030295236417006593.post-75580636071531613552017-01-05T12:26:00.000-08:002017-01-05T12:39:03.484-08:00Efeito Metaballs com JavaFXFalamos sobre como escrever <a href="http://aprendendo-javafx.blogspot.com.br/2017/01/escrevendo-pixel-por-pixel-de-um-canvas.html">pixel por pixel de um Canvas</a> e o objetivo na verdade era essa postagem aqui.<br />
<br />
Nessa postagem vamos criar o efeito <a href="https://en.wikipedia.org/wiki/Metaballs">Metaballs</a> e iremos seguir o mesmo código explicado pelo MESTRE Shiffman no vídeo abaixo, mas iremos aplicar em JavaFX. Sugiro você ver o vídeo, ler o artigo sobre <a href="http://aprendendo-javafx.blogspot.com.br/2017/01/escrevendo-pixel-por-pixel-de-um-canvas.html">escrita de pixels com JavaFX</a> e tentar fazer por você mesmo. Se não conseguir, em seguida você pode ver o código que criamos como exemplo.<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/ccYLb7cLB1I" width="560"></iframe>
<br />
<br />
<h3>
</h3>
<h3>
Nosso simples projeto</h3>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgudtwHQQaVKA13Cfg74Gk9Dx4cLQvPPuZmm4ui6HLtychSszHVxzjELLp6Lle3pzwPPLSpNBEAleF-6mKzTcccnRB-Tlm_lpKxZDk7el5r2n0C6sBhN_4_mEUAI5ntzfpNd8nmUw4Rfn2I/s1600/metaballsfx.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgudtwHQQaVKA13Cfg74Gk9Dx4cLQvPPuZmm4ui6HLtychSszHVxzjELLp6Lle3pzwPPLSpNBEAleF-6mKzTcccnRB-Tlm_lpKxZDk7el5r2n0C6sBhN_4_mEUAI5ntzfpNd8nmUw4Rfn2I/s400/metaballsfx.png" width="400" /></a></div>
<br />
<br />
Como vocês viram, o Shiffman usa <a href="https://en.wikipedia.org/wiki/Processing_(programming_language)">Processing</a>,a linguagem de programação mais bacana para criarmos efeitos visuais. A boa notícia é que tudo que fazemos com Processing podemos fazer com JavaFX. A versão original de Processing, na verdade, é baseada em Java (com versões para JavaScript e Python). Logo, tudo que você vê ele fazendo você consegue fazer também e em Java, ou seja, você se diverte e ainda exercita o uso de uma linguagem de mercado.<br />
O nosso programa vai ter duas pequenas classes, veja o código e a seguir um vídeo que fiz explicando. Se tiver dúvidas você pode perguntar no <a href="https://groups.google.com/forum/#!topic/javafx-br/pxiT7T1eNG8">nosso grupo</a> ou nos comentários<br />
<br />
<br />
<script src="https://gist.github.com/jesuino/887bb7787bc8eb0bc73c299c162d1002.js"></script>
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/VW9UO2YxvZI" width="560"></iframe>
<br />
<br />
<h3>
Conclusão</h3>
<br />
E está aberta a temporada de efeitos especiais no JavaFX! Vamos criar coisas baseadas nos vídeos do Shiffman. Em breve voltamos com mais novidades.Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-71858130082288477902017-01-04T20:38:00.003-08:002017-01-04T21:45:14.181-08:00Escrevendo pixel por pixel de um CanvasJá falamos aqui sobre o <a href="http://aprendendo-javafx.blogspot.com.br/2014/08/desenhando-livremente-com-canvas-e-o.html">Canvas</a> e um uso básico do mesmo. Hoje vamos mostrar um pouco mais desse poderoso <a href="http://aprendendo-javafx.blogspot.com.br/2014/02/a-classe-node-e-seus-principais.html">node</a>, mostrando como manipular os pontos de imagem ou o pixel.O pixel representa cada ponto da sua tela e cada ponto tem uma cor RGB (vermelho, verde e azul), adicionalmente também a opacidade do ponto, mas hoje só falaremos do RGB.<br />
<h3>
Escrevendo pixel a pixel usando o Canvas</h3>
<div>
<br /></div>
<div>
Ao criar o canvas, temos que acessar o Graphics2d se quisermos trabalhar nele. O mesmo Graphics2d permite acesso a uma classe do tipo <a href="http://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/PixelWriter.html">PixelWriter</a> e com ela podemos configurar a cor de cada pixel de um canvas! Veja o exemplo mais básico possível que gera um canvas com pixels aleatórios:</div>
<div>
<br /></div>
<div>
<script src="https://gist.github.com/jesuino/8c5d632b713a2562abf08b53776b205c.js"></script>
<br />
<div>
<br /></div>
<div>
O código é simples:</div>
<div>
<br /></div>
<div>
- Inicialmente criamos um canvas e pegamos o pixel writer dele;</div>
<div>
- Há um <i>for de for</i> que passará por cada posição do canvas - indo até a largura e a altura da aplicação;</div>
<div>
- Nesse <i>for de for </i>criamos valores aleatórios para R (vermelho), G (verde) e B (azul);</div>
<div>
- Então escrevemos o pixel usando o PixelWriter com uma cor que criamos a partir dos valores aleatórios;</div>
<div>
- Por fim temos toda a já conhecida parte do JavaFX, que é de criar uma scene, uma raiz.</div>
<div>
<br /></div>
<div>
O resultado é algo similar ao seguinte sempre com valores aleatórios ao executar a aplicação:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGc_xCAUl24N-Wxwaw5OLXA8kH_9j1olUKkH06KWgE13KRwYCYGJTAkosV-CGYS_Jy6JG9DxqkPCQK6T0uyDSWqc6qj5E54Z_C63pXdWVO_OeLUR9joYFhnlYt9ysDyeCYiormECIk6sfr/s1600/canvas-pixel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGc_xCAUl24N-Wxwaw5OLXA8kH_9j1olUKkH06KWgE13KRwYCYGJTAkosV-CGYS_Jy6JG9DxqkPCQK6T0uyDSWqc6qj5E54Z_C63pXdWVO_OeLUR9joYFhnlYt9ysDyeCYiormECIk6sfr/s400/canvas-pixel.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Temos bastante pontos cinza, pois o ponto cinza equivale a valores iguais de RGB! </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Olhem mais um exemplo bacana:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFfIVJoDIJjiDC_i2mBDnYMfdrOJFuG4Bxarlq03WRgYnz15ZSQj0KTk7H8-BaS9MdkXjcAGLS6VWXPg_lTykzZzm1C1SackV43VdtSxrj-77gD_mOTin4ITcejcT9UbQbhvqBO_1O-IUp/s1600/vermelhao.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFfIVJoDIJjiDC_i2mBDnYMfdrOJFuG4Bxarlq03WRgYnz15ZSQj0KTk7H8-BaS9MdkXjcAGLS6VWXPg_lTykzZzm1C1SackV43VdtSxrj-77gD_mOTin4ITcejcT9UbQbhvqBO_1O-IUp/s400/vermelhao.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Veja o código</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<script src="https://gist.github.com/jesuino/a7a294b6456b710e177671633e72051c.js"></script>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Bem, essa foi uma postagem rápida. Pretendo criar algo bacana com isso, então precisava introduzir essa classe. Até mais, pessoal!</div>
</div>
</div>
Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-74555712067121081502016-12-22T19:08:00.002-08:002016-12-22T19:08:52.467-08:00Livro gratuito sobre JavaFX<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFvwi-fu47XKuvlt8A-1_5AJcijm9-LhSNC0NlR1dB_G8APzP0qeT5o_A083wuwh5UlfnWzBv20B-g1h9ZpAzft5gWUcNyjJWdngLaUXhqyJGfmnZ2UDuae3xw2lP3G1EQ1PQWnLXNzApF/s1600/javafx.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="315" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFvwi-fu47XKuvlt8A-1_5AJcijm9-LhSNC0NlR1dB_G8APzP0qeT5o_A083wuwh5UlfnWzBv20B-g1h9ZpAzft5gWUcNyjJWdngLaUXhqyJGfmnZ2UDuae3xw2lP3G1EQ1PQWnLXNzApF/s400/javafx.jpeg" width="400" /></a></div>
<br />
<br />
E aconteceu! Esse blog virou um pequeno livro de bolso sobre JavaFX! Agradeço a todos que acessam o blog, são 400 acessos diários(em média), com picos de 1000 acessos por dia!<br />
<br />
O livro é simples, com o conteúdo do blog, mas somente as partes básicas. Há também um código testado e preparado para ser importado no Eclipse para uso.<br />
<br />
<a href="http://aprendendo-javafx.blogspot.com.br/p/livros.html">Veja a página do livro para mais informações.</a><br />
<br />
Será que há mais livros por vir? Veremos.<br />
<br />Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com2tag:blogger.com,1999:blog-1030295236417006593.post-43188326743007874972016-11-27T15:43:00.001-08:002016-11-27T15:43:03.590-08:00Um pequeno temporizador (ou cronômetro)Nessa rápida postagem iremos compartilhar com vocês um pequeno temporizador feito em JavaFX.<br />
<br />
A ideia é bem simples, um temporizador configurável que pode ser usado como auxílio aos que gostam da <a href="https://pt.wikipedia.org/wiki/T%C3%A9cnica_pomodoro">técnica pomodoro</a>. Já quem quer aprender JavaFX, esse é só um código de exemplo de uso da classe Animation.<br />
<br />
A ideia é bem simples: você escolhe um tempo e o temporizador começa a diminuir aquele tempo tocando um "tick" até chegar a 0 e então um som de bomba explodindo é tocado.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2HsrPuz0l56LplwNUmwI_4QqroUsjJ-1U4elTAX1bgOOoizjzQ7DW7jXESptlsyFj9Rwqm4-3n6SVZGbhijZxyJimUagwVZj_Bg__7f7r7WYcFECsTIFujMPlADXnuTutOgAlozJBM2kY/s1600/Screenshot-Temporizador+%252814%253A55%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2HsrPuz0l56LplwNUmwI_4QqroUsjJ-1U4elTAX1bgOOoizjzQ7DW7jXESptlsyFj9Rwqm4-3n6SVZGbhijZxyJimUagwVZj_Bg__7f7r7WYcFECsTIFujMPlADXnuTutOgAlozJBM2kY/s400/Screenshot-Temporizador+%252814%253A55%2529.png" width="400" /></a></div>
<br />
O código não é complexo, veja abaixo e sem seguida uma pequena explicação:<br />
<br />
<ul>
<li>A aplicação funciona dependendo da classe Animation que é controlada pelo único botão da aplicação. Criamos uma animação sem fim(sem tempo para parar), mas que a sua execução é controlada pelo botão;</li>
<li>Para que seja executado código a cada um segundo, adicionamos um KeyFrame na animação que é executado a cada 1 segundo e tem por ação o método <b><i>atualizaValores;</i></b></li>
<li>Quando o botão é clicado, verificamos o estado atual dele (se ele está com texto PARAR ou Começar) e de acordo com esse valor paramos ou iniciamos a animação e também pegamos o atual valor selecionado no slider;</li>
<li>No método <i style="font-weight: bold;">atualizaValores </i>é onde tudo acontece. Nele atualizamos o valor do label, atualizamos o tempo restante e também tocamos o áudio;</li>
<li>O método atualizaLabelTempo é responsável por pegar o valor em segundos e transformar no formato mm:ss, para que seja mostrado no label;</li>
</ul>
<div>
Essa é a ideia básica dessa app feita em menos de 1 hora. Você pode p<a href="https://github.com/AprendendoJava/javafx-basic-tutorials/tree/master/blog-javafx/timer-com-javafx">egar o código no github</a> e melhorar para adicionar mais funcionalidades! Veja abaixo o código final:</div>
<br />
<br />
<br />
<br />
<br />
<br />
<script src="https://gist.github.com/jesuino/8490e015cae04f063e8cffb5809cf91a.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-19332851891140319332016-09-07T23:00:00.003-07:002016-09-14T12:15:24.955-07:00[Especial] Eleições 2016: Mostrar dados abertos com JavaFXÉ amigos, mais um ano de eleições. Nós, profissionais de TI, podemos criar aplicações que exploram dados abertos. Por exemplo, já falamos aqui de uma API para as eleições de 2014:<br />
<br />
<b><a href="http://aprendendo-javafx.blogspot.com.br/2014/08/especial-eleicoes-2014-uma-aplicacao-em.html">[Especial] Eleições 2014: Uma aplicação em JavaFX e apresentando uma API Java</a></b><br />
<br />
Hoje vamos mostrar mais uma pequena aplicação para uma API criada por meu colega <a href="https://github.com/pedro-hos">Pedro</a>. Essa API permite ver as leis de vereadores da cidade de São José dos Campos, o <a href="https://github.com/pedro-hos/temis">Têmis</a>.<br />
<br />
Essa postagem também ajudara a fixar os conceitos em JavaFX que você deve ter aprendido ao ler esse blog. Caso ainda não seja tão experiente em JavaFX, siga os links que coloquei e leia os artigos, pois praticamente tudo que foi usado na aplicação já foi discutido aqui!<br />
<h3>
Dados abertos e JavaFX</h3>
<br />
JavaFX é um framework essencialmente desktop. No entanto, você pode criar sua aplicação e migrar ela para um celular, como <a href="http://aprendendo-javafx.blogspot.com.br/2014/12/especial-executando-sua-aplicacao.html">já falamos aqui</a>. O JavaFX oferece todos os recursos para facilmente criar uma aplicação visualmente atraente e útil: <a href="http://aprendendo-javafx.blogspot.com.br/2014/04/usando-tabelas-com-javafx-tableview.html">tabelas</a>, <a href="http://aprendendo-javafx.blogspot.com.br/2014/05/adicionando-efeitos-sua-aplicacao.html">efeitos</a>, <a href="http://aprendendo-javafx.blogspot.com.br/2014/08/introducao-graficos-com-javafx.html">gráficos</a> e <a href="http://aprendendo-javafx.blogspot.com.br/p/o-que-e-javafx.html">muito mais</a>.<br />
<br />
Além do mais, JavaFX é Java, ou seja, temos acesso a infinitas APIs para ajudar a acessar WEB Services, parse de arquivos, I/O, inteligência artificial e muito mais!<br />
<br />
<br />
<h3>
TemisFX</h3>
<div>
<br /></div>
<div>
Essa é a nossa aplicação:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGiRNOXShtCI0ux113EizGFBteqZNzDVX2GETxPmS4WHODZH1yTGmmAPYRNYaI3iwhpZedBosYWQ8vGZkZKDc9qE5MN5K6Jeo26_2WbyCZqYkU47IgiQZhRtwmSMMP3X_eoPanRFR7eMOJ/s1600/temis_final.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGiRNOXShtCI0ux113EizGFBteqZNzDVX2GETxPmS4WHODZH1yTGmmAPYRNYaI3iwhpZedBosYWQ8vGZkZKDc9qE5MN5K6Jeo26_2WbyCZqYkU47IgiQZhRtwmSMMP3X_eoPanRFR7eMOJ/s400/temis_final.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
A pessoa pode escolher o vereador e ao clicar no mesmo, a lista de leis é carregada e podemos selecionar uma lei para ler a mesma. Veja o vídeo:<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/KaQ8h6wWtcE" width="560"></iframe>
</div>
<div>
<br />
<br />
O funcionamento é simples, pois Nossa aplicação é simples e consiste de poucas classes. Veja abaixo:<br />
<br /></div>
<div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizKBKUs__kCRdjaC6MWq4Z-aM3kmLkxnnzuebUhXShEfAEnIsl-AOA_lJldU-Th383pF0-KwlBYZ4gLv__4FW3_3OD6B0dRsE0o1Af1hq0CoYQdKx2jVpPw1d2GP40kptUBUbdeKe6-dhB/s1600/classes_temis.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizKBKUs__kCRdjaC6MWq4Z-aM3kmLkxnnzuebUhXShEfAEnIsl-AOA_lJldU-Th383pF0-KwlBYZ4gLv__4FW3_3OD6B0dRsE0o1Af1hq0CoYQdKx2jVpPw1d2GP40kptUBUbdeKe6-dhB/s320/classes_temis.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<ul>
<li>A classe App é quem estende de <a href="http://aprendendo-javafx.blogspot.com/2012/07/sua-primeira-aplicacao-em-javafx-usando.html">Application</a>. </li>
<li>As classes Alderman e Law são representantes da resposta da API do Têmis. Elas têm os mesmos campos do JSON para que possamos transformar a resposta do Web Service REST em objeto Java;</li>
<li>TemisClientService é uma interface Java que representa as operações com a API. Já a classe TemisClientServiceImpl implementa essa interface e nela é que fazemos a chamado ao Web Service;</li>
<li>TemisClientUI é onde toda a aplicação é criada. Essa classe estende de <a href="http://aprendendo-javafx.blogspot.com/2013/03/gerenciadores-de-leiaute-basicos-ii.html">BorderPane</a> e nela criamos a lista e os outros paineis da aplicação. A<a href="http://aprendendo-javafx.blogspot.com.br/2016/09/listas-e-imagens-listview.html"> lista dos vereadores é customizada</a> através da AldermanListCell.</li>
</ul>
<div>
<br /></div>
</div>
<div>
Vamos na classe TemisClientUI. Como falamos, ela estende de BorderPane e nela temos as listas e os paines principais da aplicação. Veja o código e em seguida uma explicação sobre os diversos métodos:</div>
<div>
<br />
<script src="https://gist.github.com/jesuino/28eb240d1e701feb86f3c63c734099b7.js"></script>
</div>
<div>
<br />
<br />
<ul>
<li>Perceba que a aplicação recebe uma <a href="http://aprendendo-javafx.blogspot.com.br/2014/08/api-do-javafx-properties-listeners-e.html">boolean property</a> no construtor. A ideia é quando fizermos alguma chamada ao servidor, deixar a tela em modo de espera. Assim manipulamos essa propriedade toda vez que algo está sendo carregado; Por isso usamos uma property, podemos fazer binding dos elementos da app com essa property!</li>
<li>Em seguida criamos o painel que contém as leis. Para garantir que quando uma lei é selecionada o conteúdo é mostrado, adicionar um listener ao elemento selecionado na lista de leis. Outro ponto interessante é que o texto da lei vem como HTML já. Assim usamos o <a href="http://aprendendo-javafx.blogspot.com.br/2015/01/abrindo-e-renderizando-paginas-web-em.html">browser do JavaFX</a> para carregar aquele conteúdo em HTML. O painel das leis e o seu conteúdo fica em um SplitPane, para que o usuário possa dimensionar manualmente os paineis e facilitar a leitura;</li>
<li>O método fadeCenterPane é interessante pois ele que faz um efeito de transição quando selecionamos um vereador. Simplesmente nele tocarmos uma <a href="http://aprendendo-javafx.blogspot.com/2013/09/criando-animacoes-usando-as-transicoes.html">FadeTransition</a>;</li>
<li>Já os vereadores ao serem carregados são colocado em uma ListView que tem a orientação horizontal e tem a célula customizada;</li>
<li>Por fim, notem que a aplicação se comporta de maneira assíncrona. Isso é facilmente feito usando a <a href="http://aprendendo-javafx.blogspot.com.br/2014/08/threads-e-javafx.html">Task do JavaFX</a>. Como a mesma usa generics, conseguimos facilmente trocar os tipos usados na task, ou seja, usamos o mesmo método para pegar as leis e a lista de vereadores.</li>
</ul>
<div>
<br /></div>
<h3>
Conclusão</h3>
<div>
<br /></div>
<div>
Apresentamos a aplicação TêmisFX e falamos sobre apresentação de dados abertos com JavaFX. O código completo está no <a href="https://github.com/jesuino/temis-javafx">github</a>.</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com1tag:blogger.com,1999:blog-1030295236417006593.post-59580062460901055492016-09-05T18:54:00.002-07:002016-09-05T18:54:41.502-07:00Listas e imagens: ListViewNessa rápida postagem iremos falar sobre imagens dentro das ListView do JavaFX.<br />
<br />
<h3>
A ListView</h3>
<br />
A classe <b><i>javafx.scene.control.ListView</i></b> permite mostrar listas de algum objeto e também que seja selecionado um dos items. A ListView é um <a href="http://aprendendo-javafx.blogspot.com.br/2014/02/a-classe-node-e-seus-principais.html">Node</a>. Ou seja, você pode adicionar ela em qualquer um dos<a href="http://aprendendo-javafx.blogspot.com.br/2012/10/gerenciadores-de-leiaute-basicos-i.html"> painéis que já falamos aqui</a> e assim mostrar a lista na sua aplicação. Veja abaixo um exemplo de ListView:<br />
<br />
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSPVLfkX1IbeDOevLWPIhgEOplGIHPP-v4m87lvKary2javURVe22lGGtlLlYx4PDyU4JUrRqNw9nxCzEpHOkccEuZdkYmuaSArcyKOaE7CHZ8VKlQ_TxzmrxtER1TmVb67ZhW2dLLXOOi/s1600/Screenshot-Temis+JavaFX+Client.png" imageanchor="1"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSPVLfkX1IbeDOevLWPIhgEOplGIHPP-v4m87lvKary2javURVe22lGGtlLlYx4PDyU4JUrRqNw9nxCzEpHOkccEuZdkYmuaSArcyKOaE7CHZ8VKlQ_TxzmrxtER1TmVb67ZhW2dLLXOOi/s320/Screenshot-Temis+JavaFX+Client.png" width="320" /></a><br />
<br />
<br />
Como as <a href="http://aprendendo-javafx.blogspot.com.br/2014/04/usando-tabelas-com-javafx-tableview.html">tabelas</a>, temos um método <b><i>getItems</i></b> que permite você acessar os itens e adicionar novos. A lista pode ser vertical, como acima, ou horizontal usando o método <i style="font-weight: bold;">lista.setOrientation(Orientation.HORIZONTAL). </i>Um exemplo:<br />
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDAA-2ON-cXcHsqElSH2BtSF549dr2VvHPZZ2cMzmvDOSosCzQMXSbslUeHhjIwb_PXh9xUpPMhHXUXzWL3wx4F0XfzoQy-4Nqj5Dw6Il1Hw6YZrNSxg_FXffNcJl2fGtHV-X-4uEG7-S9/s1600/Screenshot-Temis+JavaFX+Client-1.png" imageanchor="1"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDAA-2ON-cXcHsqElSH2BtSF549dr2VvHPZZ2cMzmvDOSosCzQMXSbslUeHhjIwb_PXh9xUpPMhHXUXzWL3wx4F0XfzoQy-4Nqj5Dw6Il1Hw6YZrNSxg_FXffNcJl2fGtHV-X-4uEG7-S9/s320/Screenshot-Temis+JavaFX+Client-1.png" width="320" /></a><br />
<br />
<h3>
Customizando ListView </h3>
<br />
Cada item é adicionado em uma ListCell<TIPO>, que você pode customizar. Uma forma simples de customizar é criando sua própria ListCell (uma classe que estende de ListCell) e sobreescrever o método <b>updateItem</b>. Ao sobreescrever o método, não se esqueça de chamar <b>super.updateItem</b> e seja feliz mexendo nas configurações da célula. Importante dizer que a célula pode ter o texto mudado e também o graphics, ou seja, você pode configurar uma imagem e o texto de acordo com o objeto que você colocou no TIPO.<br />
<br />
O TIPO é o seguinte: Uma ListCell é parametrizada, ou seja, você informa o tipo de objeto que ela aceita. Assim você vai ter erros se tentar inserir outros tipos. Ou seja, se a sua lista é do tipo String, você tem erros ao inserir Integer nessa lista. O mesmo vale para a ListCell, você cria uma ListCell para o TIPO que escolher. Por fim, o tipo vale também para tipos customizados da sua aplicação.<br />
<br />
Agora que você criou sua célula, como você informa que quer usar ela na sua lista? Bem, a resposta é simplesmente informar uma fábrica de células usando o método <b>setCellFactory. </b>Não se apavore, com Java 8 você simplesmente usa o seguinte: <b>lista.setCellFactory(param -> new MinhaListCell())</b><br />
<b><br /></b>
<br />
<h3>
Um exemplo com imagem</h3>
<br />
O código abaixo esclarece tudo que mencionei:<br />
<br />
<script src="https://gist.github.com/jesuino/02d9aff21929c5247645a36aec6a5405.js"></script>
<h3>
Conclusão</h3>
<br />
Falamos brevemente de ListCell. Na verdade o objetivo dessa postagem é preparar terreno para a próxima que fala da aplicação que mostramos nos screenshots - até lá!<br />
<br />Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com1tag:blogger.com,1999:blog-1030295236417006593.post-13290376275735578892016-08-20T17:01:00.002-07:002016-08-20T17:01:48.190-07:00App de Sorteio usando JavaFXNessa postagem rápida, vamos mostrar uma aplicação útil, feita em JavaFX, que usamos nos eventos dos nossos JUG.<br />
<br />
O código original foi feito em algumas horas, depois foi melhorado para ser integrado a um <a href="http://aprendendo-javaee.blogspot.com.br/2013/04/introducao-jax-rs.html">Web Service REST</a> de outra aplicação, mas o uso básico é possível para sortear números sem sequer acessar o WS.<br />
<br />
Veja o sorteio de números:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgbDRZHZNZW9v3FjkpaFnJVLNVe0p99F4cByVNSSeaTVx3bZdzwnXaqrvrs3Ee5T8Lw-IZ4L9AzDKyOXI5mfref6I6Zi7lcuWdvuE-mGsrxD4z4hoqScDS9r2Tn5IVF6qywfCMXtMWwIQn/s1600/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgbDRZHZNZW9v3FjkpaFnJVLNVe0p99F4cByVNSSeaTVx3bZdzwnXaqrvrs3Ee5T8Lw-IZ4L9AzDKyOXI5mfref6I6Zi7lcuWdvuE-mGsrxD4z4hoqScDS9r2Tn5IVF6qywfCMXtMWwIQn/s400/Screenshot.png" width="400" /></a></div>
<br />
<br />
Após alguns sorteios você pode ver o que falta sortear e o que já foi sorteado:<br />
<div class="separator" style="clear: both; text-align: center;">
<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2mObD7fgkKeNiywjFDAdkYfxk77HwXu_Soa48eRvcfRTZB2RBSjnDFYMg-pV-mhyphenhyphenyJh14A760J8DbDcqqbpOVpm-mlRSgaMzcxBe8wF4v057uvd8uj0SeCBVRzh8wUnsnv4UehJGAeIx6/s1600/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2mObD7fgkKeNiywjFDAdkYfxk77HwXu_Soa48eRvcfRTZB2RBSjnDFYMg-pV-mhyphenhyphenyJh14A760J8DbDcqqbpOVpm-mlRSgaMzcxBe8wF4v057uvd8uj0SeCBVRzh8wUnsnv4UehJGAeIx6/s400/Screenshot.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Bem, era isso, uma postagem rápida mesmo! Espero que a aplicação seja util a alguém. O código está no <a href="https://github.com/Jug-Vale/SorteaProjeto">github do JUG Vale</a>.Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com1tag:blogger.com,1999:blog-1030295236417006593.post-7413489633021454532016-03-06T22:33:00.002-08:002016-03-06T22:38:14.463-08:00Completar automaticamente ComboBoxBaseado nessa<a href="http://www.guj.com.br/t/filtrar-item-do-combo-box-digitando-pelo-teclado-do-javafx/323230"> postagem do GUJ</a>, eu criei um simples exemplo de auto complete em <a href="http://aprendendo-javafx.blogspot.com.br/2012/08/controles-basicos-de-interface-iii.html">ComboBox</a>. O que ele basicamente faz é:<br />
<br />
<br />
<ul>
<li>Quando o usuário digita com o ComboBox selecionado, ele trabalha com uma String temporária que armazena o texto;</li>
<li>A cada tecla digitada, o conteúdo do combobox é mostrado e atualizado;</li>
<li>Se backspace é digitado, atualizamos o filtro;</li>
<li>A cada tecla digitada, mostramos os itens do combo box, quando o combo box é oculto, o filtro é limpo e a tooltip ocultada.</li>
</ul>
<div>
<br /></div>
<div>
O resultado é mais ou menos o seguinte:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGae4L9Mzs3RzvU_ftrzhe9MMSLZEJDOyhS8BQu86qGIcsygheJNMT_mj024n398du2pZwvq28seVkLrxxoRKytM87u7zLMHEShyphenhyphenlm-DBzhpCiuubhZBsdFNpjS7dptJTPuef4wWOD1ypS/s1600/gif_auto_complete.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGae4L9Mzs3RzvU_ftrzhe9MMSLZEJDOyhS8BQu86qGIcsygheJNMT_mj024n398du2pZwvq28seVkLrxxoRKytM87u7zLMHEShyphenhyphenlm-DBzhpCiuubhZBsdFNpjS7dptJTPuef4wWOD1ypS/s1600/gif_auto_complete.gif" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
O código da classe e mais uma aplicação de exemplo está abaixo. Coloquei também no <a href="https://github.com/jesuino/javafx-combox-autocomplete">github</a>, me mande PR para melhorar e há MUITAS melhorias a serem feitas, como suporte a espaço e acentos.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<script src="https://gist.github.com/jesuino/56de77be529e68384175.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com5tag:blogger.com,1999:blog-1030295236417006593.post-10207128404674820562016-02-28T00:17:00.004-08:002016-02-28T00:17:48.046-08:00Criando controles customizados com JavaFX<b>Essa é uma tradução do artigo criado por Hendrik. Veja mais no <a href="http://www.guigarage.com/2012/11/custom-ui-controls-with-javafx-part-1/">blog GuiGarage</a></b><br />
<b><br /></b>
<b><i>Por Hendrik Ebbers</i></b><br />
<b><i><br /></i></b>
<br />
Uma coisa que eu frequentemente faço com Java Swing é a customização de componentes e a criação de novos tipos de componentes. Um exemplo é o <a href="http://www.guigarage.com/2011/07/hello-world/">JGrid</a>. Desde que JavaFX foi lançado, eu quis <a href="http://www.guigarage.com/2012/11/gridfx-is-hosted-at-github/">portar o JGrid</a>. Depois de muitos experimentos e protótipos ruins, eu acho que encontrei a forma correta de fazer isso. As apresentações de <a href="http://harmoniccode.blogspot.de/">Gerrit Grunwald</a> e <a href="http://jonathangiles.net/blog/">Jonathan Giles</a> no JavaOne me ajudaram muito a fazer isso. As gravações dessas apresentações estão disponívels online (<a href="https://oracleus.activeevents.com/connect/sessionDetail.ww?SESSION_ID=2425&tclass=popup">link</a> e link - NOTA: links quebrados), então eu recomendo quem estiver interessado nesse tópico a investir algum tempo e assistir elas.<br />
<br />
<br />
<h3>
Primeiros passos</h3>
<br />
<br />
Como componente de interface no JavaFX é composto por um control(controle), uma skin("casca") e um behaviour(comportamento). Em um caso ideal, há também a parte do CSS.<br />
<br />
<img src="http://i1.wp.com/www.guigarage.com/wordpress/wp-content/uploads/2012/11/custom-components1.png?resize=877%2C181" height="131" width="640" /><br />
A melhor forma de começar é criar uma classe que herda de <i style="font-weight: bold;"><a href="http://docs.oracle.com/javafx/2/api/javafx/scene/control/Control.html">javafx.scene.control.Control</a>.</i> Essa classe é basicamente compara ao <a href="http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html">JComponent</a>. O Control deve ter as propriedades do componente e atuar como a classe principal dele porque instâncias dessa classe serão depois criadas automaticamente no códido da aplicação e serão adicionadas para a árvore da interface com o usuário(UI):<br />
<br />
<span class="pl-smi" style="background-color: white; border: 0px; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> myControl </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">=</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-smi" style="background-color: white; border: 0px; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">();</span><br />
<span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">panel</span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">getChildren()</span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">add(myControl);</span><br />
<br />
Quando programando componentes Swing na forma correta você coloca tudo que depende da visualização ou a interação com o usuário em uma classe de UI (veja <a href="http://docs.oracle.com/javase/6/docs/api/javax/swing/plaf/LabelUI.html">LabelUI</a> por exemplo). JavaFX vai além e disponibiliza uma classe de skin para toda a visualização e o layout relacionado com o código e a classe behaviour para todas as interações com o usuário.<br />
<br />
<img src="http://i0.wp.com/www.guigarage.com/wordpress/wp-content/uploads/2012/11/custom-components2.png?resize=997%2C493" height="316" width="640" /><br />
<br />
Para fazer isso em JavaFX você deve entender como as classes se relacionam. Aqui está um pequeno diagrama que mostra as relações entre essas classes:<br />
<br />
<img src="http://i0.wp.com/www.guigarage.com/wordpress/wp-content/uploads/2012/11/custom-componens3.png?resize=634%2C354" height="357" width="640" /><br />
<br />
<h3>
Criando o comportamento (classe Behaviour)</h3>
Se o seu componente é somente para visualização de dados e não há interação, é baste simples criar um comportamento. Assim, você simplesmente precisa criar um classe que herde de<b><i> com.sun.javafx.scene.control.behavior.BehaviorBase.</i></b><br />
<br />
<span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControlBehavior</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">extends</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-e" style="background-color: white; border: 0px; color: #795da3; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">BehaviorBase</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> {</span><br />
<span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControlSkin</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">(</span><span class="pl-smi" style="background-color: white; border: 0px; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-v" style="background-color: white; border: 0px; color: #ed6a43; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">control</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">) {</span><br />
<span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-v" style="background-color: white; border: 0px; color: #ed6a43; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">super</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">(control, </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">new</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-smi" style="background-color: white; border: 0px; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControlBehavior</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">(control));</span><br />
}<br />
}<br />
<br />
Alguns de vocês podem ficar confusos quando ver o pacote da classe BehavioyBase. No momento é uma API privada e normalmente você não deveria usar essas classes no seu código, mas os caras da Oracle sabem desse problema e irão providencias a classe BehaviorBase como uma API com o JavaFX 8. Então uma boa prática é usar essa classe privada agora e refatorar assim que o JavaFX for lançado(*).<br />
<br />
<b><i>NOTA: O javaFX 8 foi lançado já!</i></b><br />
<br />
<h3>
Criando a casca (classe Skin)</h3>
<div>
Depois que a classe de comportamento é criada, podemos dar uma olhada na skin. Sua classe de skin vai muito provavelmente herdar de <b><i>com.sun.javafx.scene.control.skin.BaseSkin</i></b> e criar um novo comportamento para o seu Control. O código normalmente se parece com o seguinte:</div>
<div>
<br /></div>
<div>
<span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControlSkin</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">extends</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-e" style="background-color: white; border: 0px; color: #795da3; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">SkinBase</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">{</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControlSkin</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">(</span><span class="pl-smi" style="background-color: white; border: 0px; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-v" style="background-color: white; border: 0px; color: #ed6a43; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">control</span><span style="background-color: white; color: #333333; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace; font-size: 12px; line-height: 16px; white-space: pre;">) {</span></div>
<div>
<table class="highlight tab-size js-file-line-container" data-tab-size="8" style="background-color: white; border-collapse: collapse; border-spacing: 0px; border: 0px; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 1.4; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; width: 893px;"><tbody style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">
<tr style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"></tr>
<tr style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"><td class="blob-code blob-code-inner js-file-line" id="file-skin-java-LC4" style="background-color: transparent; border: 0px; margin: 0px; outline: 0px; overflow: visible; padding: 1px 10px !important; position: relative; vertical-align: top; word-wrap: normal;"><span class="pl-v" style="border: 0px; color: #ed6a43; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;"> super</span><span style="font-style: inherit; font-variant: inherit; line-height: inherit; white-space: pre;">(control, </span><span class="pl-k" style="border: 0px; color: #a71d5d; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">new</span> <span class="pl-smi" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControlBehavior</span><span style="font-style: inherit; font-variant: inherit; line-height: inherit; white-space: pre;">(control));</span>
<span style="font-style: inherit; font-variant: inherit; line-height: inherit; white-space: pre;">
}</span>
<br />
<span style="font-style: inherit; font-variant: inherit; line-height: inherit; white-space: pre;">}</span>
<br />
<br /></td></tr>
</tbody></table>
</div>
<h3>
Criando o controle</h3>
<div>
A última classe que precisamos é o controle. Primeiro criamos uma classe vazia:</div>
<div>
<br /></div>
<div>
<span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">extends</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-e" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">Control</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> {</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">() { }</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">}</span></div>
<div>
<br /></div>
<div>
Nesse ponto nós temos uma falha nas dependências das nossas classes. A skin conhece o behavior e o control. Aqui tudo parece correto, no entanto, no código da aplicação você vaim simplesmente criar um novo controle e usar como eu mostrei antes. O problema é que a classe de controle não sabe nada sobre a skin ou o behavior. Esse foi um dos maiores desafios quando eu estava aprendendo JavaFX.</div>
<div>
<br /></div>
<h3>
Juntando as coisas</h3>
<div>
<br /></div>
<div>
O que inicialmente parece um grande problema, é na verdade parte do poder disponibilizado pelo JavaFX. Com JavaFX é muito fácil criar diferente visualizações (skins) para os controles. Nessa parte você pode customizar a aparência dos componentes usando CSS. Como a skin é a parte principal da aparência, ela deve ser definida no CSS também. Assim, invés criar um objeto skin para o controle manualmente, você simplesmente define a classe skin que deve ser usada no seu controle. A criação e tudo mais é automaticamente feito pelas APIs do JavaFX. Para fazer isso, você deve ligar o seu controle a uma classe CSS.</div>
<div>
Primeiramente, crie um novo arquivo no seu projeto. Eu acredito que a melhor prática é usar o mesmo pacote que o controle está e não um arquivo CSS criado sob <b><i>src/main/resource</i></b>:</div>
<div>
<br /></div>
<div>
<img src="http://i1.wp.com/www.guigarage.com/wordpress/wp-content/uploads/2012/11/custom-components4.png?resize=433%2C349" /></div>
<div>
<br /></div>
<div>
Dentro do seu CSS você deve especificar um novo seletor para o seu componente e adicionar a skin como uma propriedade. Isso deveria parecer como o seguinte exemplo:</div>
<div>
<br /></div>
<div>
<div>
<span class="pl-e" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.custom-control</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> {</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-c1" style="background-color: white; border: 0px; color: #0086b3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">-fx-skin</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">: </span><span class="pl-s" style="background-color: white; border: 0px; color: #183691; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;"><span class="pl-pds" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"</span>com.guigarage.customcontrol.MyCustomControlSkin<span class="pl-pds" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">;</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">}</span></div>
<div>
<br /></div>
<div>
Assim que você criar o CSS, você tem que definir o mesmo no seu controle. Portanto, você deve configurar o caminho para o arquivo css e o seletor dos seus componentes:</div>
<div>
<br /></div>
<div>
<span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">extends</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-e" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">Control</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> {</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">() {</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> getStyleClass()</span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">add(</span><span class="pl-s" style="background-color: white; border: 0px; color: #183691; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;"><span class="pl-pds" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"</span>custom-control<span class="pl-pds" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">);</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> }</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">protected</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-smi" style="background-color: white; border: 0px; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">String</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">getUserAgentStylesheet</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">() {</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">return</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-smi" style="background-color: white; border: 0px; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">class</span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">getResource(</span><span class="pl-s" style="background-color: white; border: 0px; color: #183691; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;"><span class="pl-pds" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"</span>customcontrol.css<span class="pl-pds" style="border: 0px; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">"</span></span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">)</span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">toExternalForm();</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> }</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">} </span></div>
<div>
<br /></div>
<div>
Depois que todas essas coisas foram feitas corretamente, JavaFX vai criar uma instância de skin para o seu controle. Você não precisa se preocupar com instanciação ou o mecanismo de depdendëncias. Nesse ponto eu gostaria de agradecer Jonathan Giles, que dedicou um tempo para codificar a integração do css para o gridfx comigo e explicou todo o mecanismo e benefícios.</div>
</div>
<div>
<br /></div>
<h3>
Acesso à Skin e Behavior</h3>
<div>
Normalmente não há a necessidade de acessar a Skin e o Behavior através do controle, mas se você precisar disso, você pode acessá-los da seguinte forma:</div>
<div>
<br /></div>
<div>
<img src="http://i2.wp.com/www.guigarage.com/wordpress/wp-content/uploads/2012/11/custom-controls5.png?resize=663%2C409" /></div>
<div>
<br /></div>
<div>
<div>
Como controler.getSkin() rece um javafx.scene.control.Skin e não a classe SkinBase você deve fazer um cast se precisar do behaviour:</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<i>((SkinBase)getSkin()).getBehavior();</i></div>
<div>
<br /></div>
<h3>
Uma solução para os que odeiam CSS</h3>
<div>
Para alguns de vocës esse mecanimos parece um pouco exagerado. Talvez vocë simplesmente precise de um controle na sua aplicação e você não planeja usar uma skin com CSS e fazer tudo isso. Para esse caso de uso, há um ótimo <i>workaround</i> na API do JavaFX. Você pode ignorar toda a parte do CSS e configurar a classe skin no seu controle usando código:</div>
<div>
<br /></div>
<div>
<span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">class</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">extends</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-e" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">Control</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> {</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">public</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> </span><span class="pl-en" style="background-color: white; border: 0px; color: #795da3; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControl</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">() {</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> setSkinClassName(</span><span class="pl-smi" style="background-color: white; border: 0px; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">MyCustomControlSkin</span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">class</span><span class="pl-k" style="background-color: white; border: 0px; color: #a71d5d; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;">.</span><span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">getName());</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;"> }</span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; line-height: 16px; white-space: pre;">}</span></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div>
O benefício dessa forma de trabalho é que refatorar pacotes e nome de classes não vai quebrar o seu código e você não precisa de um arquivo CSS extra. Por outro lado, há uma grande desvantagem. Você não poderia usar skins definidas por CSS em qualquer extensão do seu controle. Acho que toda API pública, como o GridFX, deveria usar a forma com CSS. Em alguns casos de uso internos, a forma hardcoded(essa que falamos agora) é muito mais rápida.</div>
<div>
<br /></div>
</div>
</div>
<h3>
Conclusão</h3>
<div>
Agora nós criamos um controle, uma skin e um behavior que está funcionando bem e pode ser adicionado na árvore UI da sua aplicação. Mas, como acontece com o Swing, simplesmente herdar de JComponent não levará você a ver nada na tela. Então o próximo passo é adicionar estilo e organizar o layout do seu componente. Irei falar disso no meu próximo artigo.</div>
<div>
Se você quiser dar uma olhada em algum componente existente veja <a href="https://github.com/guigarage/gridfx">jgridfx</a> ou <a href="https://github.com/JFXtras/jfxtras-labs">JFXtras</a>. No jgridfx os seguintes arquivos batem com esse artigo:</div>
<div>
<div>
<br /></div>
<div>
<ul>
<li>com.guigarage.fx.grid.GridView (control)</li>
<li>com.guigarage.fx.grid.skin.GridViewSkin (skin)</li>
<li>com.guigarage.fx.grid.behavior.GridViewBehavior (behavior)</li>
<li>/src/main/resources/com/guigarage/fx/grid/gridview.css (css)</li>
</ul>
</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com0tag:blogger.com,1999:blog-1030295236417006593.post-5868502077290206702016-02-17T01:25:00.001-08:002016-02-17T01:25:13.774-08:00Um CRUD com JavaFX usando banco de dadosDevido ao sucesso da postagem anterior <a href="http://aprendendo-javafx.blogspot.com.br/2016/02/um-crud-com-javafx.html">Um CRUD com JavaFX</a>, resolvi estender a mesma para falar sobre o acesso a um banco de dados MySQL utilizando a mesma estrutura do artigo anterior.<br />
<br />
<h3>
Acessando banco de dados com Java</h3>
<div>
<br /></div>
<div>
Esse é talvez um dos assuntos mais buscados por quem está aprendendo Java. Há muitas referências a isso na internet, inclusive uma série de artigos que o criado desse blog escreveu há mais de 5 anos atrás para o JavaFree, veja: <a href="http://javafree.uol.com.br/artigo/874102/Acessando-dados-com-Java-1%C2%BA-parte-Simples-Dao.html">Acessando dados com Java: 1º parte - Simples Dao</a> - <a href="http://javafree.uol.com.br/artigo/874441/Acessando-Dados-com-Java-Parte-2-Prevendo-problemas.html">Acessando Dados com Java: Parte 2 - Prevendo problemas</a> - <a href="http://javafree.uol.com.br/artigo/874971/Acessando-Dados-com-Java-Parte-3-Hibernate-Annotations.html">Acessando Dados com Java: Parte 3 - Hibernate Annotations</a></div>
<h3>
Preparando o banco</h3>
<div>
O primeiro passo nosso é garantir que você tenha o MySQL instalado(que depende do sistema operacional sendo utilizado, Linux ou outros) e uma vez feito isso, entre no MySQL e então seguir alguns passos. Para esse artigo foi criado o seguinte:</div>
<div>
<br /></div>
<div>
<br />
<ul>
<li>Usuário <b><i>contas_app</i></b> com senha <i><b>aprendajavafx</b></i>;</li>
</ul>
</div>
<div>
<br /></div>
<div>
<b><i>CREATE USER 'contas_app'@'localhost' IDENTIFIED BY 'aprendajavafx';</i></b></div>
<div>
<br />
<br />
<ul>
<li> Banco de dados contas <b><i>crud-contas; </i></b></li>
</ul>
</div>
<div>
<b><i><br /></i></b></div>
<div>
<b><i>CREATE DATABASE `crud-contas` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci</i></b></div>
<div>
<br /></div>
<div>
<br />
<ul>
<li>Garanta os privilégios do usuário <b><i>contas_app</i></b> para o banco <b><i>crud-contas</i></b></li>
</ul>
</div>
<div>
<br /></div>
<div>
<div>
<b><i>mysql> use crud-contas</i></b></div>
<div>
<b><i>Database changed</i></b></div>
<div>
<b><i>mysql> GRANT ALL PRIVILEGES ON * . * TO 'contas_app'@'localhost';</i></b></div>
</div>
<div>
<br /></div>
<div>
<br />
<ul>
<li>Tabela Contas com os campos que precisamos</li>
</ul>
</div>
<div>
<br /></div>
<div>
<div>
<b>create table contas( </b></div>
<div>
<b> id int auto_increment, </b></div>
<div>
<b> concessionaria varchar(30) not null, </b></div>
<div>
<b> descricao varchar(1000) not null, </b></div>
<div>
<b> data_vencimento date not null,</b></div>
<div>
<b> primary key(id) </b></div>
<div>
<b>); </b></div>
</div>
<div>
<br /></div>
<div>
Notem que o ID é auto_increment, ou seja, o MySQL vai dar o ID para nós. Se inserirmos alguns valores de teste, podemos notar que o ID já foi preenchido:<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSV7nJXdUWbk6nspzLsZzL6p1O9kF9mjvB-u2-vjPFMAHp-R99zpXMD0ixfaow9xWpTqFWkRHB9guB7bXniVmLuviUBLcVM5RIi8qp_sQmtxcHE9W3-AzIc_m218WNc5jHWXZxwl4PJDvo/s1600/dados.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSV7nJXdUWbk6nspzLsZzL6p1O9kF9mjvB-u2-vjPFMAHp-R99zpXMD0ixfaow9xWpTqFWkRHB9guB7bXniVmLuviUBLcVM5RIi8qp_sQmtxcHE9W3-AzIc_m218WNc5jHWXZxwl4PJDvo/s640/dados.png" width="640" /></a></div>
<h3>
</h3>
<h3>
Criando uma classe para acesso ao banco de dados</h3>
<div>
Conforme falamos no artigo anterior, para trocar onde os dados serão armazenados nós iremos criar uma implementação de <b>ContasService </b>e trocar o tipo retornado no método <b>getNewInstance</b>. </div>
<div>
<br /></div>
<div>
Para falarmos com o nosso banco de dados MySQL, precisamos ter o Driver JDBC no classpath da aplicação, pois é ele quem possibilita a comunicação de uma aplicação Java com o banco. Por isso, baixe o <a href="https://dev.mysql.com/downloads/connector/j/">driver JDBC do MySQL</a> e coloque no classpath da aplicação.<br />
<br />
A implementação do banco de dados simplesmente envia comandos SQL para o MySQL invés de abrir e manipular arquivos, assim temos que:<br />
<br />
* Salvar significa realizar um INSERT com os dados da conta passada;<br />
* Buscar é trazer dados usando SELECT e transformar em uma lista de contas;<br />
* Apagar é realizar um DELETE;<br />
* Por fim atualizar é a realização de um UPDATE.<br />
<br />
Claro que tudo pode ser facilitado usando um framework que faz o mapeamento de objetos para o modelo relacional de banco de dados, como o Hibernate, mas por hoje vamos ficar no básico! Finalmente, veja como ficou nossa classe ContasDBService (lembre-se que todo o código pode ser encontrado no <a href="https://github.com/AprendendoJava/javafx-basic-tutorials/tree/master/blog-javafx/contas-crud-javafx">github</a>):</div>
<div>
<br /></div>
<div>
<br /></div>
<script src="https://gist.github.com/jesuino/d9a44deeff25e78c4b1d.js"></script>Williamhttp://www.blogger.com/profile/12980844418405775676noreply@blogger.com6