18 de fev de 2014

Um "Olá Mundo" com JavaFX 8

Olá pessoal!

Essa é uma postagem rápida que foge do nosso cronograma habitual e meu objetivo aqui é falar das mudanças mais impactantes do JavaFX 8, que vem com o Java 8.

Java 8 vem preparado para a execução de aplicações JavaFX

Você não precisa colocar o JAR do JavaFX no classpath como fazemos para o JavaFX 2.x. Com essa nova versão, você já pode compilar e executar as aplicações sem ter que fazer nenhum tipo de configuração extra.

Lambdas vão facilitar muito tratamentos de eventos e muito mais

A maior novidade do Java 8 e a adição do Lambda. Com isso, fica muito mais fácil fazer programação funcional utilizando essa linguagem orientadas a objetos . Basicamente o que temos é uma nova forma de escrever implementações de interfaces funcionais (interfaces que só têm um método abstrato, pois no Java 8 interfaces pode ter implementação padrão). 
Claro que poderíamos criar diversos artigos só sobre isso, pois a API básica também sofre adição de um pacotes só de interfaces funcionais, o java.util.function. James Weaver resumiu aqui as mudanças, mas notem que essas mudanças não são na API, mas na forma que podemos escrever código. Segue um exemplo bem básico de tratamento de evento de botão:
Como é:
// Usando classes internas
button.setOnAction(new EventHandler() {
  @Override public void handle(ActionEvent e) {
    System.out.println("Botão clicado...");
  }
});

Com uso de Lambdas :
// Usando expressões Lambdas
button.setOnAction(e -> System.out.println("Botão clicado..."));

Mudanças na API do JavaFX 8

Esse é outro tópico que não vou me estender muito, pois a Oracle já colocou no roadmap do JavaFX o que foi adicionado nessa versão. As novidades são excitantes: novos controles, suporte "embebbed"(exemplo: raspberry pi), suporte a gráficos 3d, entre outras...

Um Olá Mundo

Essa foi uma postagem bem rápida. Gostaria de compartilhar com vocês a construção de um Olá Mundo. Simplesmente baixei a mais nova build do Java 8 e já comecei o vídeo. Até a próxima, pessoal!


11 de fev de 2014

A classe Node e seus principais atributos: Aplicação de exemplo

Olá Pessoal,

Na última postagem nós falamos da classe Node do JavaFX. Ela é a classe chave de toda a arquitetura do JavaFX 2 e aprendendo ela de forma efetiva, você vai ficar apto a desenvolver aplicações mais rapidamente!
A nossa aplicação de exemplo usa um nó como algo e o nó pode sofrer diversas modificações. Veja abaixo um screenshot.



O ponto maior dessa aplicação é demonstrar que existem propriedades comuns que são aplicáveis a qualquer classe que está em uma aplicação JavaFX. Logo, no painel à esquerda, notem diversos controles. Eles irão modificar os mais famosos atributos do nó.

A mágica está em trocar o controle para mudar os seus atributos sem mexer em nenhuma outra parte do código. Em termos práticos, você troca de um texto para um botão e os controles do lado esquerdo continuam funcionando e são aplicados sem qualquer outra modificação no código. Em seguida, podemos trocar o botão por qualquer outro controle: figuras, um vídeo, controles, etc... Veja como isso é feito nas linhas de código que selecionei abaixo:

// aqui criamos o nó
Node alvo = criaNo();

// usamos ele em diversos pontos
// aqui vamos "amarrar" as propriedades dos controles da tela com as
// propriedades do nó
sldEscalaX.valueProperty().bindBidirectional(alvo.scaleXProperty());
sldEscalaY.valueProperty().bindBidirectional(alvo.scaleYProperty());
sldRotacao.valueProperty().bindBidirectional(alvo.rotateProperty());

// um listener para os botões que movimentam o nó
EventHandler cliqueBotoesMovimento = new EventHandler() {

 @Override
 public void handle(ActionEvent evt) {
  // de acordo com o botão clicado vamos manipular nosso nó
  Object botaoClicado = evt.getSource();
  if (botaoClicado == btnDecrementaX) {
   alvo.setTranslateX(alvo.getTranslateX() - 1);
  } else if (botaoClicado == btnIncrementaX) {
   alvo.setTranslateX(alvo.getTranslateX() + 1);
  } else if (botaoClicado == btnDecrementaY) {
   alvo.setTranslateY(alvo.getTranslateY() - 1);
  } else if (botaoClicado == btnIncrementaY) {
   alvo.setTranslateY(alvo.getTranslateY() + 1);
  }
 }
};
// muda o efeito
cbEfeitos.getSelectionModel().selectedItemProperty()
 .addListener(new ChangeListener() {
  @Override
  public void changed(
    ObservableValue valor,
    String antigo, String novo) {
   switch (valor.getValue().toString()) {
   case BORRAR:
    alvo.setEffect(efeitoBorrar);
    break;
   case SOMBRA:
    alvo.setEffect(efeitoSombra);
    break;
   case REFLEXAO:
    alvo.setEffect(efeitoReflexao);
    break;
   case NENHUM:
    alvo.setEffect(null);
    break;
   default:
    break;
   }
  }
 });

Se você quiser fazer isso, pegue o código no github importe no Eclipe e localize o seguinte método:

private Node criaNo() {
 // Modifique esse método para criar o nó que você quiser e retornar! O
 // programa vai funcionar independente do nó que você cira
 Text texto = new Text("\\o/ exemplo \\o/  ");
 texto.setFont(new Font(40));

 Rectangle rect = new Rectangle(200, 150);
 rect.setFill(Color.RED);

 HBox caixinha = new HBox(20);
 caixinha.getChildren().addAll(new Rectangle(80, 60), new Circle(30),
   new Button("Um botão de teste"), new Text("um texto"));
 caixinha.setAlignment(Pos.CENTER);

 // crie seus próprios nós e retorne aqui!
 return texto;
}

Veja que há outros possíveis nós que estão no código acima. Use um deles e rode o programa novamente, aí pode brincar com os controles do lado esquerdo e verá que eles se aplicam da mesma forma que o texto anterior se aplicava!

Um ponto interessante desse programa é que eu criei um "handler" genérico para todos os eventos do mouse! Mais detalhes sobre isso pode ser encontrado nesse artigo(em inglês) e mais sobre tratatamento de eventos vocês podem ver nesse artigo aqui no nosso blog.
Outro ponto, e que vamos explicar futuramente, é o uso de Binding. É uma técnica para evitarmos muito código fazer com que duas propriedades tem o mesmo valor e sejam atualizados quando elas mudam o valor. No nosso caso alguns campos do nó alvo têm o seu valor alterado quando mexemos nos controles, veja:

sldEscalaX.valueProperty().bindBidirectional(alvo.scaleXProperty());
sldEscalaY.valueProperty().bindBidirectional(alvo.scaleYProperty());
sldRotacao.valueProperty().bindBidirectional(alvo.rotateProperty());

Há também o uso dos efeitos Reflection, DropShadow e BoxBlur, que vamos abordar futuramente!
Por final, fiz um vídeo usando esse programa para ilustrar melhor o que estou falando.


Divirta-se e avise se tiver qualquer dúvida!