21 de out de 2012

Gerenciadores de leiaute básicos I

Organizar os componentes que estão em uma aplicação gráfica é sempre um desafio, pois você tem que posicionar e dimensionar cada elemento que adicionar a sua aplicação. Os gerenciadores de leiaute servem para auxiliar você nessa missão.
O JavaFX traz alguns gerenciadores pronto para auxiliar você. Hoje nós vamos mostrar quase todos e falar um pouco dessa parte da API. O leitor assíduo, no entanto, já deve ter percebido o uso de alguns em artigos anteriores.

O que é um gerenciador de leiaute?

O conceito é bem simples. Quando você vai criar sua aplicação, a "telinha" dela, você tem necessidades comuns de posicionamento e dimensionamento dos componentes. Exemplo: as vezes você quer colocar eles alinhados verticalmente ou orizontalmente, quer empilhar, colocar em uma "grade" e por aí vai. Fazer isso na mão já é difícil e ainda teremos que recriar o código para cada nova aplicação que escrevermos...
Um gerenciador de leiaute é uma classe que faz esse gerenciamento para você de acordo com uma forma de posicionamento já estabelecida. Em termos práticos, a classe VBox, por exemplo, organiza os componentes verticalmente e podemos adicionar nela os componentes de nossa aplicação como os botões, rótulos, tabelas, ou até outros gerenciadores de leiaute. As principais classes do JavaFX que exercem essa função são:
  • VBox: Alinha os componentes verticalmente;
  • HBox: Alinha os componentes horizontamente;
  • StackPane: Empilha um componente sobre o outro;
  • BorderPane: Divide os elementos em regiões e coloca um componente em cada uma desses regiões
  • FlowPane:  Ajeita os componentes de acordo com uma orientação e com o fluxo da aplicação;
  • GridPane: Cria uma grade com os componentes. É possível informar qual a posição do componente na grade;
  • AnchorPane: Os componentes filhos são "ancorados"  em uma parte do painel;
  • TilePane: Um painel com pedaços (Tile vem do inglês e significa azulejo) para os componentes semelhante ao GridPane, mas permite tratamento dos "Tiles";
Todas essas classes estão no pacote javafx.scene.layout.

Arquitetura

Como você já deve ter percebido, essas os gerenciadores aceitam classes que herdam de Node e os próprios são Nodes também. Eles estendem diretamente de Pane cujo método mais comum é getChildren.

O método ObservableList<Node> getChildren() retorna os elementos filhos em uma ObservableList. Essas listas simplesmente atualizam automático a visualização quando adicionamos componentes nela. Com ela podemos adicionar os componentes um a um, usando um array ou simplesmente adicionar quantos elementos quiser na chamada do método. Métodos mais comuns da ObservableList são:
  • addAll(E... elements): adiciona 1 ou mais elementos em uma só chamada de método. Você pode passar vários elementos também ou até um array. É possível adicinar um único componente usando o método add;
  • removeAll: remove todos os elementos da lista; Com o método remove, é possível remover um componente de um determinado índice ou um objeto informado.
  • setAll (E... elements) : remove os elementos anteriores e adiciona os novos informados; Temos também o método set onde é possível "setar" o nó de um determinado índice.
Há outros métodos. As listas observáveis são poderosas classes do mundo JavaFX, no entanto, esses são os mais usados frequentemente. Lembre-se que essa lista é tipada para Node, o que significa que você só pode adicionar elementos desse tipo ou subclasses de Node e também reforçando que mexer na lista já garante que a sua aplicação seja atualizada.

Conhecendo na prática

Depois de tanto conceito e uma pequena exploração da API, vamos criar aplicações simples que usam essas classes e dessa forma vamos ver em ação tudo que falamos, tornando mais prazeroso o aprendizado e a exploração da API. Hoje vamos mostrar só três classes: VBoxHBox e StackPane(quem leu posts anteriores sabe que já usamos essas classes aqui).

VBox

Um dos gerenciadores mais simples, a classe VBox simplesmente alinha os componentes verticalmente e permite determinar o espaçamento entre eles e ainda o alinhamento. Abaixo um código que simplesmente adiciona umas forma geométricas a uma VBox e em seguida a explicação do mesmo.

VBox caixaVertical = new VBox(); // 1
caixaVertical.setSpacing(5); // 2
caixaVertical.setAlignment(Pos.CENTER); // 3

//4
caixaVertical.setTranslateX(10);
caixaVertical.setTranslateY(20);

// 5
Rectangle retanguloAzul = new Rectangle(40, 20);
Rectangle retanguloVerde = new Rectangle(40, 20);
Rectangle retanguloVermelho = new Rectangle(40, 20);

retanguloAzul.setFill(Color.BLUE);
retanguloVerde.setFill(Color.GREEN);
retanguloVermelho.setFill(Color.RED);
  
//6
caixaVertical.getChildren().addAll(retanguloAzul, retanguloVerde, retanguloVermelho);

  1. Criando nossa VBox. Não estamos enviando nada no construtor, mas é possível informar o espaçamento entre os componentes diretamente no construtor;
  2. Informamos o espaçamento. Esse atributo é do tipo Double e ele informa qual distância os componentes devem entre eles;
  3. Aqui determinamos que os componentes fiquem centralizados no nosso VBox. Podemos também escolher colocar eles para esquerda, direta, entre outros. Veja o enum Pos.
  4. Nessa linha mudamos a posição X e Y do nosso VBox. O interessante é que os componentes filhos terão que obedecer a posição do pai, para isso eles também são deslocados automaticamente;
  5. Criamos nossos componentes que estarão no VBox. Criamos retângulos e lembrando que eles herdam de Node. Isso é um requisito para nosso gerenciador.
  6. Agora adicionamos todos de uma vez. A ordem de adicão é a ordem que eles serão mostrados na aplicação. 
O resultado está abaixo. Lembre-se de sempre fuçar bastante as classes, essa é a melhor forma de aprender e se diverter :)


HBox

Não iremos entrar em detalhes dessa classe por que ela trabalha exatamente igual a VBox, com exceção que ela alinha os componentes horizontalmente. Abaixo temos uma imagem de como o código acima se comportaria simplesmente trocar a "instanciação" de VBox para HBox.

StackPane

Um comportamento não muito comum, mas que pode ser útil em diversas aplicações, é o trazido pela classe StackPane. Nela os componentes são empilhados uns nos outros, ou seja, em entrou primeiro fica embaixo do segundo e assim por diante. O exemplo de código abaixo mostra isso muito claramente. Perceba que não iremos explicar o código pois ele é semelhante ao mostrado anteriormente, a exceção está no resultado visual. Estamos desenhando uma bandeira do Brasil (ou tentando), para isso criamos um retângulo, um losango um círculo e, o mais díficil, um arco. Usamos as formas geométricas do JavaFX para fazer isso e no fim colocamos em um gerenciador do tipo StackPane, veja que ele empilha as imagens de forma que por final temos algo que é quase uma bandeira do Brasil... Quase...

StackPane painelEmpilhador = new StackPane();
Rectangle retangulo = new Rectangle(220, 120);
retangulo.setFill(Color.GREEN);

Polygon losango = new Polygon();
losango.getPoints().addAll(new Double[]{
     50.0, 50.0,
     150.0, 0.0,
     250.0, 50.0,
     150.0, 100.0,
     50.0, 50.0 });
losango.setFill(Color.YELLOW);
Path arco = new Path();
MoveTo moveTo = new MoveTo();
moveTo.setX(0.0);
moveTo.setY(0.0);

ArcTo arcTo = new ArcTo();
arcTo.setX(55.0);
arcTo.setY(0.0);
arcTo.setRadiusX(50.0);
arcTo.setRadiusY(50.0);

arco.getElements().add(moveTo);
arco.getElements().add(arcTo);
arco.setStroke(Color.WHITE);

arco.setRotate(180);
arco.setStrokeWidth(5);

Circle circulo = new Circle(30, Color.BLUE);
  
painelEmpilhador.getChildren().addAll(retangulo, losango, circulo, arco);

Mais uma vez note que a ordem que adicionamos os componentes é muito importante. Veja o resultado:


Conclusão

Foram apresentados os gerenciadores de leaiute e também uma introdução prática mostrando os mais básicos. JavaFX facilita o uso dessas classes e ainda traz diversos gerenciadores de leiaute, alguns completamente novos, outros semelhantes aos disponíveis no Swing.
Fiquem antenados que em breve teremos o segundo post da série.

15 de ago de 2012

Controles Básicos de Interface III


Na terceira parte de nossa série sobre os controles do JavaFX, vamos falar das caixas de combinação, ComboBox, e caixas de escolhas, ChoiceBox. Ambas permitem você escolher um valor entre um conjunto de opções. Além do que mostrar como usar o controle, vamos ainda explorar os eventos que ele oferece,criando uma aplicação um pouco mais interessante do que algo inútil

Muitas opções, uma possível escolha

Os dois controles que vamos apresentar hoje funcionam de maneira muito semelhante, a maior diferença está na forma visual que elas são apresentadas dentro da sua aplicação. Ambas permitem que você faça a escolha de uma só opção entre diversas outras. no entanto, há uma pequena diferença visual entre elas e o ComboBox permite que você fabrique as células que serão mostradas. Criar fábrica de células é um assunto que facilmente ocuparia uma postagem inteira, você pode ver mais sobre isso aqui.
Para tratar dos dados individualmente da parte visual, usamos em ambas classes o conceito de SelectionModel, onde abstraimos a parte de seleção de dados. Temos duas abstrações: MultipleSelectionModel(permite selecionar vários itens ao mesmo tempo) e SingleSelectionModel(permite selecionar um único item ao mesmo tempo.
Hoje também vamos falar de um conceito novo e específico do JavaFX, então vamos nos limitar a mostrar o ComboBox e uma aplicação super simples, no entanto, o leitor deve pode acessar a documentação do ChoiceBox e criar a mesma aplicação usando ele. Enfim, vamos ao código!

Selecione a cor

Para demostrar o ComboBox, criamos uma aplicação bem simples que permite que você selecione a cor da cena e de um retângulo através do uso desse controle de interface. Ao selecionar a cor, a mudança já é imediata. Como fazemos isso? Confira o código e em seguida tenha acesso

package main;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Main extends Application {

 String cores[] = { "Blue", "Black", "Red", "White", "Green", "Yellow",
   "Gray", "Pink", "Salmon" };

 public static void main(String[] args) {

  launch();
 }

 @Override
 public void start(Stage palco) throws Exception {
  StackPane raiz = new StackPane();

  HBox opcoes = new HBox(10);
  opcoes.setAlignment(Pos.CENTER);

  final Rectangle retangulo = new Rectangle(300, 100);

  ComboBox cbCorCena = new ComboBox<>(); // 1
  ComboBox cbCorRetangulo = new ComboBox<>();

  cbCorCena.getItems().addAll(cores); // 2
  cbCorRetangulo.getItems().addAll(cores);

  opcoes.getChildren().addAll(cbCorCena, cbCorRetangulo);

  raiz.getChildren().addAll(retangulo, opcoes);

  final Scene cena = new Scene(raiz, 450, 250);
  palco.setTitle("Uso de ComboBox");
  palco.setScene(cena);
  palco.show();
  // 3
  cbCorCena.getSelectionModel().selectedItemProperty()
    .addListener(new ChangeListener() {
     @Override
     public void changed(
       ObservableValue valorObservado,
       String valorAntigo, String valorNovo) {
      cena.setFill(Color.valueOf(valorNovo));
     }

    });
  cbCorRetangulo.getSelectionModel().selectedItemProperty()
    .addListener(new ChangeListener() {
     @Override
     public void changed(
       ObservableValue valorObservado,
       String valorAntigo, String valorNovo) {
      // 4
      retangulo.setFill(Color.valueOf(valorNovo));
     }

    });
  cbCorCena.getSelectionModel().select(0); // 5
  cbCorRetangulo.getSelectionModel().select(1);
 }
}


  1. Começamos instanciando uma ComboBox. Perceba que ela faz uso de genéricos, onde informamos que tipo de dado serão os itens contidos nela, no nossa caso, String;
  2. Nessa linha adicionamos os itens. Isso é feito de forma semelhante com a qual adicionamos itens a um componente pai como o Grupo, VBox, HBox, entre outros. Nesse caso estamos adicionando uma lista de Strings, pois esse é o tipo aceitado por essa combobox;
  3. Para observar quando o usuário escolhe algum valor no Combox, adicionamos um ouvinte ao valor observável a propriedade do item selecionado. Isso pode parecer bastante estranho, mas em breve você vai se acostumar. JavaFX traz uma API com atributos diferentes, onde nós podemos observar as modificações feitas nesses atributos e tomar alguma ação. Novamente isso é feito através de Listeners, no nosso caso usamos um listener de mudança, o ChangeListener. Note que o uso dele é bastante semelhante ao uso dos listeners de botões. Em resumo, nós estamos observando o valor selecionado do combox através de um listener, quando ele muda, nós trocamos a cor de fundo da cena;
  4. A classe Color do JavaFX é bastante interessante e contém muito mais do que um aglomerado de constantes para definir cores. É possível também converter o valor de texto de uma cor para um objeto Color. É isso o que fazermos aqui;
  5. Por fim nós usamos o método select do modelo de seleção para escolher uma cor. Esse método equivale a ação de um usuário ao escolher uma cor na combobox usando a sua aplicação, ou seja, isso também vai disparar o ouvinte de mudança que falamos na explicação 3.
Por fim, essa é a aplicação resultante:


Conclusão

Hoje nós mostramos o combobox e também apresentamos um conceito muito importante do JavaFX que são as "Properties". Você já deve ter percebido que há muito coisa a ser esclarecida e faremos isso aos poucos. 
Já está chegando o dia da nossa primeira aplicação do "mundo real", vamos apresentar mais alguns conceitos e em breve poderemos começar a criar coisas mais interessantes com JavaFX.

1 de ago de 2012

Controles Básicos de Interface II

Vamos para mais um post e nesse vamos falar sobre mais alguns controles de interface, especificamente sobre botões agrupados, mas que permitem a seleção individual, e também sobre a caixa de checagem, que representam um valor booleano (sim ou não, verdadeiro ou falso).

Várias possibilidades, uma escolha

Os botões de rádio, RadioButton, ou os botões alternados, ToggleButton, permitem apresentar um grupo de botão no qual é permitido selecionar somente um. Esse controle de não deixar dois botões serem selecionados é feito atráves de um grupo de botões, ToggleGroup, que recebe os mesmos e então controla o comportamento deles. 
O uso desse tipo de botão é feito em diversos casos onde você tem escolhar bem pré-definidas, por exemplo: campos para escolha de sexo, alternativas de questões multivaloradas com uma resposta válida, entre outros.

Três estados, um controle

O segundo controle de interface que vamos mostrar hoje é simples e bastante utilizado em formulários para pedido de informações de usuários quando temos uma questão direta (exemplo: "Você Fuma?"). Estamos falando da caixa de checagem, CheckBox, que na verdade tem três estados: selecionado, não selecionado e indeterminado(você pode escolher se quer habilitar esse estado ou não). 
Pode parecer estranho, mas um problema que podemos ter é pedir a entrada de um usuário e o mesmo sequer ligar para esse campo, daí ele larga o campo em branco, logo, como você vai fazer para saber se ele não responde ou não marcou de propósito? 

A hora mais feliz

Vamos agora colocar esses botões em uma tela JavaFX e  mostrar algumas classes novas para posicionar os componentes. Vamos avançar um pouco o level, já são 5 tutoriais só com aplicações simples, temos que colocar um pouco mais de emoção e daqui a pouco já estaremos trabalhando com aplicações grandes com JavaFX. Enfim, como já está se tornando algo clássico do presente blog, vamos ao código e em seguida explicações dos pontos mais interessantes ou novos.
O programa abaixo representa um programa de uma pesquisa simples sobre programação. Com ele vamos mostrar o que discutimos nesse post e algumas coisas novas.


import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Principal extends Application {

 public static void main(String[] args) {
  launch();
 }

 @Override
 public void start(Stage palco) throws Exception {
  VBox raiz = new VBox(10);
  raiz.setTranslateX(10);
  raiz.setTranslateY(20);

  Label lblTitulo = new Label("Pesquisa sobre Programação");
  lblTitulo.setUnderline(true); // 1

  final TextField txtNome = new TextField();
  HBox hbNome = new HBox(10); // 2
  hbNome.getChildren().addAll(new Label("Nome"), txtNome);

  HBox hbSo = new HBox(20);
  ToggleButton tbLinux = new ToggleButton("Linux"); // 3
  tbLinux.setSelected(true);
  ToggleButton tbWindows = new ToggleButton("Windows");
  ToggleButton tbMac = new ToggleButton("Mac");
  final ToggleGroup tgSo = new ToggleGroup(); // 4
  tgSo.getToggles().addAll(tbLinux, tbWindows, tbMac); // 5
  hbSo.getChildren().addAll(new Label("Sistema Operacional utilizado"),
    tbLinux, tbWindows, tbMac);

  final ToggleGroup tgLinguagem = new ToggleGroup();
  HBox hbLinguagens = new HBox(20);
  RadioButton rbJava = new RadioButton("Java"); // 6
  rbJava.setSelected(true);
  RadioButton rbC = new RadioButton("C");
  RadioButton rbPython = new RadioButton("Python");
  tgLinguagem.getToggles().addAll(rbJava, rbC, rbPython);
  hbLinguagens.getChildren().addAll(
    new Label("Linguagem de programação Predileta:"), rbJava, rbC,
    rbPython);

  final CheckBox chkFrequencia = new CheckBox("Programa todo dia?"); // 7
  final CheckBox chkGosto = new CheckBox("Gosta de programação?");
  chkGosto.setAllowIndeterminate(true); // 8
  chkGosto.setIndeterminate(true);

  Button btnSubmeter = new Button("Submeter pequisa");
  btnSubmeter.setOnAction(new EventHandler() {

   @Override
   public void handle(ActionEvent evt) {

    System.out.println("\t\tResultado da pesquisa para \""
      + txtNome.getText() + "\"\n");
    // Podemos não ter um SO selecionado
    ToggleButton tbSo = (ToggleButton) tgSo.getSelectedToggle(); // 9
    System.out.print("Sistema Operacional predileto: ");
    System.out.println(tbSo == null ? "Não selecionado." : tbSo
      .getText());

    // Deve ter uma linguagem selecionada
    RadioButton rbLinguagem = (RadioButton) tgLinguagem
      .getSelectedToggle();
    System.out.println("Linguagem de programação: "
      + rbLinguagem.getText());
    // 10
    System.out.println((chkFrequencia.isSelected() == true ? "P"
      : "Não p") + "rograma todo dia.");

    System.out.print("Gosta de programação: ");
    if (chkGosto.isSelected()) {
     System.out.println("Sim.");
     // 11
    } else if (chkGosto.isIndeterminate()) {
     System.out.println("Não respondido.");
    } else {
     System.out.println("Não.");
    }
    System.out.println("\n\n");
   }
  });

  raiz.getChildren().addAll(lblTitulo, hbNome, hbSo, hbLinguagens,
    chkFrequencia, chkGosto, btnSubmeter);

  Scene cena = new Scene(raiz, 450, 250);
  palco.setTitle("Tratando eventos");
  palco.setScene(cena);
  palco.show();
 }
}


  1. Já começamos mostrando uma propriedade do Label. Se você chamar esse método e enviar true, ele será sublinhado;
  2. Esse componente é novo, mas o primo dele, VBox, funciona de forma muito semelhante. As propriedades são exatamente as mesmas, a diferença é que a HBox os componentes são organizados horizontalmente;
  3. Nessa linha estamos criando o tão falado botão alternado. Vamos usar três. Daqui a pouco teremos que adicionar ele a um grupo junto com outros botões alternados, assim somente um poderá ser escolhido nesse grupo, mas há a possibilidade de não escolher nenhum. Perceba que estamos informando no construtor o texto que ele irá mostrar;
  4. O grupo que falamos no passo anterior é representado pela classe ToggleGroup. Ele agrupo objetos do tipo Toggle, que é a classe pai do ToggleButton e do RadioButton;
  5. Nessa linha simplesmente adicionamos os botões já declarados para o grupo, dizendo que eles não podem ser selecionados simultaneamente;
  6. Semelhante ao ToggleBox, temos o RadioButton. A maior diferença está na aparência e que um grupo de RadioButton não permite um botão não selecionado;
  7. Aqui usamos uma caixa de checagem. A String enviada no construtor também é o texto associado a ela;
  8. Dizemos que essas caixas de checagem têm três estados. Nessa linha habilitamos o terceiro estado, o estado indeterminado (quântico?);
  9. Dentro do listener anônimo do botão, estamos lendo as propriedades dos controles de interface apresentados. Essa linha especificamente retorna o Toggle selecionado. Como sabemos que esse grupo contém toggles do tipo ToggleButton, já fazemos um "cast" para esse tipo. Se nada estiver selecionado, null é retornado;
  10. O isSelected retorna um valor booleano para informar se essa caixa está selecionada;
  11. Por fim(ufa), usamos o método isIndeterminate para sabermos se o estado dessa CheckBox é indeterminado.
Como sempre, você deve pode baixar o projeto anexado ao final do post para aprender mais e explorar esses novos componentes.

Conclusão

Mostramos mais alguns controles simples de interface, dessa vez os botões que dão ao usuário certa chance de escolha. Veja que após aprender campos de texto, botões e os organizadores de layouts que mostramos até agora, você já está apto a criar pequenas aplicações. Então, não perca tempo e nos mostre tudo o que vocês tem para oferecer.

28 de jul de 2012

Tratamento de Evento Simples e o Botão

Vamos continuar falando de controles de interface e esse artigo será dedicado a somente um componente: o Botão. O motivo disso é que para falar de botão iremos falar de tratamento de evento, logo, precisaremos focar nisso, pois esse conhecimento é muito utilizado em qualquer aplicação.

Tratamento de evento

Tratar evento é determinar qual código será executado de acordo com uma ação do usuário. O usuário interage com sua aplicação através da interface, e dela ele faz diversas coisas: passa o cursor do mouse sobre um componente, arrasta coisas, clica, move o cursor para dentro ou para fora de um componente, entre outros. Qualquer componente é passível de sobre ações desse tipo por parte do usuário, logo, na classe Node podemos tratar qualquer um desses eventos. No post de hoje, no entanto, não iremos falar de todos eles, mas só de um que é o evento de ação. Quando o usuário clica em um botão, ele dispara esse evento, hoje iremos apresentar o botão, fazer um programa simples com ele e explicar como tratar o clique em um botão. Futuramente iremos falar mais sobre como tratar cada um desses outros eventos quando entrarmos em detalhes na classe Node.

Botões e Ouvintes

Botões estão em todos os lugares, com certeza você deve ter clicado em algum botão hoje :). No JavaFX, um botão pode ser usado através da classe Button. No entanto, simplesmente adicionar um botão na cena não ajuda em muita coisa, você deve informar para ele o que deve ser feito assim que um usuário clicar no mesmo. Isso é feito através de ouvintes de evento, que são classes que implementam uma determinada interface.
No caso de botão, temos o atributo onAction que é do tipo da interface EventHandler. Essa interface exige que você implemente o método handle, pois é esse método que será chamado quando você clicar no botão. Em resumo, você deve criar uma classe que implementa essa interface e informar ao botão uma instância dessa classe para que o botão chame o método quando o usuário do seu programa clicar nele! Indo um pouco mais a fundo, note que também essa interface usa genéricos para determinar o tipo de atributo que o método deverá receber, no nosso caso, o botão chama o método e envia um instância de ActionEvent, classe que contém diversas informações sobre o evento ocorrido.
Nossa, muita informação! Mas isso ficará melhor nas próximas linhas, pois mostremos exemplos de código e tudo ficará mais claro.

Clique em mim!

Vamos começar mostrando um exemplo do clássico clique em mim para assim demonstrar o tratamento mais simples possível de evento. A nossa classe ouvinte, ou tratadora de evento se encontra abaixo e em seguida uma breve explicação do código.
import javafx.event.ActionEvent;
import javafx.event.EventHandler;

public class TratadorEvento implements EventHandler { // 1


 @Override
 public void handle(ActionEvent evento) { // 2
  System.out.println("Evento tratado por uma classe externa");
 }

}

  1. Conforme já falamos, a classe destinada a tratar eventos deve implementar a Interface EventHandler. Nesse caso também fica claro o uso de Genéricos, onde devemos informar um tipo de classe que herda de Event, no caso informamos o ActionEvent, pois é o que o botão requer;
  2. Esse é o método que será chamado quando clicarmos no botão.O parâmetro evento será enviado pelo gerador do evento, no caso o botão, e deles poderíamos saber tudo de quem gerou o evento.
Mas de quem esse tratador de evento trata eventos? O próximo passo é informar para um botão qual será o seu tratador de evento. Veja abaixo que uso duas linhas para isso e basicamente criamos um botão e informamos quem será o tratador de evento através do método setOnAction.

Ótimo, já sabemos tratar eventos, mas e se você não quiser criar uma classe para toda vez que quiser tratar um clique? Você pode utilizar um classe anônima. Outra possibilidade é usa a própria classe atual para ser quem irá tomar alguma ação ao clique do usuário.
Para ilustrar tudo isso, criamos uma simples aplicação com três botões e as três formas de se registar um tratador de evento. O código abaixo mostra essa aplicação e também explica diretamente no comentário!

package main;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

//Se quisermos que essa classe trate evento, ela deve herdar de EventHandler
public class Principal extends Application implements EventHandler {

 public static void main(String[] args) {
  launch();
 }

 @Override
 public void start(Stage palco) throws Exception {
  VBox raiz = new VBox(20);
  raiz.setAlignment(Pos.CENTER);
  raiz.setTranslateY(5);

  Button botao1 = new Button("Clique em mim! (Tratador externo)");
  Button botao2 = new Button("Clique em mim! (Class Anônima)");
  Button botao3 = new Button("Clique em mim! (Própria classe)");

  // usamos a classe TratadorEvento para cuidar dos eventos
  botao1.setOnAction(new TratadorEvento());
  // Criando uma instância de uma classe anônima para tratar evento
  botao2.setOnAction(new EventHandler() {

   @Override
   public void handle(ActionEvent evento) {
    System.out.println("Evento tratado por uma classe anônima!");
   }
  });
  // o botão 3 usa essa própria classe para tratar seus eventos
  botao3.setOnAction(this);

  raiz.getChildren().addAll(botao1, botao2, botao3);

  Scene cena = new Scene(raiz, 300, 200);
  palco.setTitle("Tratando eventos");
  palco.setScene(cena);
  palco.show();

 }

 @Override
 public void handle(ActionEvent evento) {
  System.out.println("Evento tratado na próxima classe!");
 }
}


A aplicação final bem como o que será impresso no console é mostrado na imagem abaixo

Conclusão

Mostramos como tratar eventos de um botão com JavaFX. Esse post foi meio parado e chato, mas isso foi necessário. Em breve mostraremos outros elementos de interface e iremos querer dar mais vida aos nossos programas. Isso só pode ser feito tratando eventos :). Como sempre, segue abaixo o projeto do Eclipe caso você queira baixar e explorar mais.

27 de jul de 2012

Controles Básicos de Interface I

Fazendo jus ao seu principal objetivo, JavaFX oferece muitos controles de interface entre simples rótulos para mostrar texto até complexas tabelas com milhares de registros. Nesse artigo vamos mostrar os controles mais básicos de interface que JavaFX oferece.

Controles de interface

Todos os controles que o JavaFX oferece herdam da classe Control. Como alguns já devem ter deduzido, Control vai herdar em algum momento de Node, mas nesse caso ele antes herda de Parent.
Logos todos os controles usufruem com atributos como height, maxHeight, width, minWidth, entre outros.  O destaque fica para o tooltip, onde você pode informar um texto informativo para o controle quando o usuário deixa o cursor do mouse em cima dele por alguns segundos.
Tooltip em ação
Os controles são muito fáceis de lidar, no entanto, muitos tem suas características especifícas, o que leva a abordargem complicada para somente um post, então iremos separar a abordagem dos controles em vários posts.

Rótulos, campos de texto,  separadores e controles deslizantes

Hoje serão apresentados os controles mais simples possíveis, deixando para artigos futuros outros controles que exigem tratamento de evento ou maior conhecimento prévio. Hoje vamos mostrar rótulos, campos de texto, separados e controles deslizantes.  Não vamos perder mais tempo e vamos para o código!
package main;

import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.Slider;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ControlesSimples extends Application {

 public static void main(String[] args) {
  launch();
 }

 @Override
 public void start(Stage palco) throws Exception {
  VBox raiz = new VBox(10); // 1
  raiz.setAlignment(Pos.CENTER); // 2

  Label rotuloDemo = new Label("Sou um rótulo de texto!"); // 3
  rotuloDemo.setTooltip(new Tooltip(
    "Esse é um rótulo para mostrar textos de forma simples")); // 4

  TextField campoTexto = new TextField("Digite algo"); // 5
  campoTexto.setTooltip(new Tooltip(
    "Campo de texto para entrada de uma só linha "));

  TextArea areaTexto = new TextArea("Digite algo com várias linhas"); // 6
  areaTexto.setTooltip(new Tooltip(
    "Campo de texto para entrada de múltiplas linhas"));

  Separator separadorHorizontal = new Separator(); // 7
  Separator separadorVertical = new Separator(Orientation.VERTICAL); // 8
  Slider deslizante = new Slider(); // 9
  deslizante.setShowTickLabels(true); // 10
  deslizante.setShowTickMarks(true); // 11
  deslizante
    .setTooltip(new Tooltip(
      "O controle deslizante tem um valor numérico de acordo com sua posição"));

  raiz.getChildren().addAll(rotuloDemo, campoTexto, areaTexto,
    separadorVertical, separadorHorizontal, deslizante);

  Scene cena = new Scene(raiz, 300, 400);
  palco.setTitle("Controles Básicos I");
  palco.setScene(cena);
  palco.show();
 }
}



  1. Nessa linha introduzimos um novo componente pai, ou seja, um componente que podemos colocar outros dentro dele. Nesse caso a VBox, que irá organizar os componentes verticalmente. O construtor informa o espaçamento entre os componentes, no nosso caso 10;
  2. Você também pode determinar qual o posicionamento dos componentes dentro da VBox. Você usa o enum Pos para informar qual posicionamento quer. Nessa linha, informamos o posicionamento CENTER, logo todos os componentes serão posicionados no centro da nossa VBox;
  3. Esse é nosso primeiro controle de interface apresentado um Label, ou o rótulo. Esse componente nada mais é do que um texto estático, semelhante ao Text, mas herda de Control, o que significa que ele é um controle de interface, no entanto, o usuário não muda o texto do Label diretamente. Como você já deve ter deduzido, o Label é um Node, assim como todos os controles e assim como e qualquer componente dentro da Cena do JavaFX. Pense quão poderoso esse detalhe arquitetural é!
  4. Os controles tem algumas características em comum e uma delas é a possibilidade de informar um Tooltip, que nada mais é um texto demostrativo informado quando mantemos o mouse sobre o componente;
  5. Nessa linha criamos um campo de texto, o TextField. Esse campo, ao contrário do Label, permite a modificação do usuário diretamente. Futuramente você pode recuperar esse texto através do método getText();
  6. Semelhante ao campo de texto, temos o uma área de texto. Não há muita diferença entre essas duas classes, na verdade a maior diferença é que o TextArea permite a entrada de várias linhas e também contém propriedades para trabalhar com essa característica. Detalhe que a TextArea e o TextField, ambos herdam de TextInputControl;
  7. Nessa linha mostramos um separador horizontal. Ele é sem graça assim mesmo, só serve para separar as coisas. No entanto, lembre-se que ele é um... Node e também um controle;
  8. Aqui também criamos um separador, mas esse fica na vertical conforme informado pelo Enum Orientation;
  9. O controle deslizando, ou Slider, permite você escolher um valor numérico dentro de uma faixa determinada. De acordo com a posição do controle, você terá um valor numérico que pode ser recuperado depois através do método getValue().
  10. Se você quiser que o controle deslizante mostre marcas para indicação relativa de qual valor o Slider tem no momento, você deve chamar o método setShowTickLabels que vai configurar se devem aparecer essas marcas, ou não (true, false);
  11. Na linha anterior, mostramos como colocar marcas, nessa linha chamamos o método setShowTickMarks e informamos que queremos ver números que indicam o valor do controle deslizante.
Finalmente, olhe como ficou nossa aplicação:


Conclusão

Hoje nós introduzimos os controles mais básicos do JavaFX, mas não fizemos nada de interessante por que ainda não falamos de tratamento de ações do usuário na sua aplicação. Fique ligado que o próximo post será dedicado ao botão (classe Button) e nele você irá começar a dar vida as suas aplicações JavaFX.
Bem, não preciso repetir que agora entra sua vez para você explorar esse componentes lendo a documentação, e, como ponto de partida, você pode usar o projeto Eclipse abaixo. Até a próxima!

24 de jul de 2012

Imagens e Formas Geométricas

Esse é o terceiro artigo desse blog de menos de uma semana de existência e já temos 500 visitas! 

Hoje iremos falar de como mostrar imagens e figuras geométricas em sua aplicação JavaFX. O artigo será um pouco mais complexo, no entanto, nada que umas três lidas não ajude. Com certeza o leitor já deve ter explorado os outros dois posts anteriores e ido muito além do mostrado. A idéia desse blog é exatamente essa: dar ao leitor uma base e ele se divertir pelas páginas da Javadoc do JavaFX, pois essa é a melhor forma de aprender, se divertindo! Então chega de papo e vamos ao que interessa.

Mostrando Imagens

Mais uma vez devo repetir que fazer as coisas em JavaFX é muito simples, principalmente mostrar imagem. Para quem veio do Swing, sabe que até isso era difícil como podermos ver nesse post do site da DevMedia. Por outro lado, no moderno JavaFX necessitamos, mais uma vez, seguir dois simples passos:
  • Carregar a imagem. Para isso usamos a classe Image. Perceba que essa classe é uma representação alto nível de uma imagem, sendo que a mesma pode vir de um InputStream, um arquivo do seu computador e até mesmo uma URL da internet, sem você se preocupar com qualquer outra coisa;
  • Mostrar a imagem. Visualizamos a imagem através da classe ImageView. Repetimos o mesmo discurso para dizer que ImageView é um Node e é ele que adicionamos à nossa aplicação, aplicamos efeitos, animações etc (calma, iremos mostrar tudo em posts futuros).
Após saber disso, você entenderá perfeitamente que com três linhas de código podemos ter uma imagem em uma aplicação JavaFX. Mas código só daqui a pouco :)

Forma Geométricas

Todas as formas geométricas do JavaFX, adivinhe, também são Nodes e podem sofrer efeitos, transformações e animações, além de ter diversas propriedades em comum. Você pode ver as figuras geométricas oferecidas pelo JavaFX no pacote javafx.scene.shape. Todas as figuras geométricas herdam de Shape (que por sua vez herda de... Node), portanto temos propriedades comuns só para as figuras geométricas, entre as quais destacamos:
  • fill: O preenchimento da figura geométrica. Esse é um parâmetro do tipo Paint, que representa ou uma cor simples(exato: azul, verde, rosa...) ou um gradiente complexo;
  • stroke: Também do tipo Paint, mas se aplica a linha que envolve a forma geométrica;
  • strokeWidth: A largura da "stroke".

Hora de Código

Ufa, hora de se divertir. No código atual iremos mostrar a carga de uma imagem e algumas figuras geométricas, ficando a seu cargo baixar o projeto anexado e fazer algo mais elaborado e divertido. Se formos explorar todas as propriedades de cada forma geométrica, estaríamos sendo redundantes, verbosos e chatos e programação se aprende com ação e não exposição :). 
Lembre-se: se você se sentir perdido, leia os posts anteriores para maiores informações. Abaixo o código e em seguida a explicação dos pontos mais interessantes:

package main;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;


public class GraficosImagens extends Application {

 private final String IMG_URL = "http://www.oracle.com/ocom/groups/public/@otn/documents/digitalasset/402460.gif";

 public static void main(String[] args) {
  launch();
 }

 @Override
 public void start(Stage palco) throws Exception {
  Image imagem = new Image(IMG_URL); // 1
  ImageView visualizadorImagem = new ImageView(imagem); // 2
  visualizadorImagem.setTranslateX(80); // 3
  visualizadorImagem.setTranslateY(5); // 4

  Text textoInformativo = new Text(
    "Algumas figuras Geométricas desenhadas com JavaFX");
  textoInformativo.setTranslateX(30);
  textoInformativo.setTranslateY(70);

  Rectangle retangulo = new Rectangle(100, 40); // 5
  retangulo.setTranslateX(5);
  retangulo.setTranslateY(90);
  retangulo.setFill(Color.GREEN); // 6

  Circle circulo = new Circle(30);
  circulo.setTranslateX(160);
  circulo.setTranslateY(110);
  circulo.setFill(Color.YELLOW);

  Circle circuloBranco = new Circle(30);
  circuloBranco.setTranslateX(240);
  circuloBranco.setTranslateY(110);
  circuloBranco.setStroke(Color.BLACK); // 7
  circuloBranco.setStrokeWidth(3.0); // 8
  circuloBranco.setFill(Color.WHITE);

  Ellipse elipse = new Ellipse(30, 10);
  elipse.setTranslateX(320);
  elipse.setTranslateY(110);
  elipse.setFill(Color.BLUE);

  Group componentes = new Group(); // 9
  componentes.getChildren().addAll(visualizadorImagem, textoInformativo,
    retangulo, circulo, circuloBranco, elipse); // 10
  Scene cena = new Scene(componentes, 360, 150);
  palco.setTitle("Gráficos e Imagens em JavaFX");
  palco.setScene(cena);
  palco.show();
 }
}

  1. Nessa linha carregamos nossa imagem usando uma URL da internet. Lembrando que essa não é a única maneira, podemos também usar um arquivo ou qualquer coisas que forneça um InputStream;
  2. Agora criamos o nó da imagem e informamos que imagem será mostrada no construtor;
  3. Usamos uma propriedade nova nessa linha e ela nem é só do ImageView, é da classe Node! Com o translateX informamos a posição X(imagine o posicionamento como um plano cartesiano) de um componente no pai. O método set serve para configurar um valor, você já viu o uso dele em classes como o Stage;
  4. Fazemos o mesmo descrito em 3, mas agora para a posição Y. ATENÇÃO: Posicionar componentes assim não é legal de ser feito em aplicações grandes, vamos mostrar em breve os gerenciadores de leiaute do JavaFX;
  5. Aqui já estamos criando uma forma geométrica, um Retângulo (Rectangle). De acordo com a forma criada, teremos parâmetros que devem ser informados. No caso do retângulo, informamos a largura e a altura;
  6. Mudamos a cor padrão da forma geométrica (preta) para verde. Note que aqui usamos uma constante da classe Color;
  7. É informado a cor da linha que envolve essa forma geométrica, nesse caso: preta;
  8. Também aumentamos a largura (ou grossura) da linha;
  9. Outra novidade nesse código: a classe Group. Como o próprio nome disse, usamos ela para agrupar outros nós(classes que herdam de javafx.scene.Node). Ela é um nó de nós, ou seja, podemos aplicar efeito, animar, transformar que isso será aplicado a todos os nós;
  10. Finalmente usamos um novo método dos filhos do grupo que é adicionar todos os nossos nós de uma vez. Podemos fazer isso, ou adicionar um por um.
Abaixo vejam como a aplicação ficou:


Olha, está começando a ficar interessante o negócio, hein?

Conclusão

Mostramos mais alguns componentes do JavaFX, dessa vez as classes de imagem e formas geométricas e aprendemos alguns pequenos novos métodos e classes. Vamos avançando! 

23 de jul de 2012

Tocando Áudio e Vídeo

Nesse artigo vamos mostrar como criar aplicações com capacidade de tocar áudio e vídeo com JavaFX. Serão mostradas duas aplicações bastante simples com o objetivo de mostrar essas características. Futuramente teremos artigos mais avançados nesse assunto.
Se você nunca fez nada com JavaFX até agora sugiro que você dê uma olhada nesse post para criar sua primeira aplicação. A partir dele você estará preparado para esse artigo.

Carregando, tocando e mostrando um vídeo

Tocar vídeo em JavaFX é tão simples que chega a assustar quem já tentou tocar um vídeo usando Java anteriormente. Nós só temos que seguir três pequenos passos:
  1. Carregar. Você primeiramente deve carregar a mídia que vai tocar. A mídia pode estar no seu disco rígido como em um um servidor.
  2. Tocar. A partir da mídia, você deverá controlar a mesma: tocar, parar, pausar, etc.
  3. Mostrar. Nesse ponto iremos colocar o vídeo dentro de sua aplicação JavaFX.
Para realizar esses três passos temos três classes JavaFX que ficam no pacote javafx.scene.media. Para 1 nós temos a classe Media, 2 podemos fazer com a classe MediaPlayer e finalmente conseguimos o passo três com o uso da MediaView. O uso dessas classes é muito simples, abaixo temos o código de um aplicação de exemplo e em seguida um breve explicação de cada linha nova. 

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;

public class TocandoVideo extends Application {

 private String VIDEO_URL = getClass().getResource(
   "/video/creativecommons.mp4").toString();

 public static void main(String[] args) {
  launch();
 }

 @Override
 public void start(Stage palco) throws Exception {

  Media media = new Media(VIDEO_URL); // 1
  MediaPlayer mediaPlayer = new MediaPlayer(media); // 2
  MediaView mediaView = new MediaView(mediaPlayer); // 3

  StackPane raiz = new StackPane();
  raiz.getChildren().add(mediaView); // 4
  Scene cena = new Scene(raiz, 600, 400);
  palco.setTitle("Tocando Video em JavaFX");
  palco.setScene(cena);
  palco.show();

  mediaPlayer.play(); // 4
 }
}
  1. Nessa linha estamos carregando o nosso vídeo. No construtor é recebido a URL do vídeo que pode ser ou um arquivo local ou um link para um vídeo publicado em algum servidor;
  2. Após informar a mídia, nós temos que criar um player ("tocador") que será responsável por interagir com a midia em sí e assim poder tocar, parar, pausar (entre outras ações) o referido vídeo.
  3. Nós já temos o vídeo e já sabemos como controlar ele, no entanto, temos que adicionar ele a nossa aplicação JavaFX para que o vídeo seja mostrado. 
  4. O MediaView é uma classe que herda de  Node, ou seja, podemos adicionar ele a qualquer Node que herda de Parent (não se preocupe, futuramente teremos posts específicos sobre essas classes). Nessa linha nós adicionamos o vídeo ao pai.
  5. Por fim tocamos o vídeo através do método play(). Há também outros métodos para controle do vídeo, sendo possível criar um player dinâmico, iremos mostrar isso no futuro também
Conforme mostrado acima, são quatro linhas para podermos tocar um vídeo em uma aplicação JavaFX. Veja abaixo o resultado:

Carregando e tocando áudio

Se tocar vídeo exige menos de 4 linhas de código, tocar áudio exige ainda menos: 2. Semelhante ao que fizemos com vídeo, o áudio deve ser carregado e então tocado. O áudio, no entanto, não dispõe de uma classe para visualização, já que essa não é necessária e temos somente uma classe necessária para a carga e execução do áudio, a classe AudioClip. Claro que você pode criar um player se achar necessário. Vejam abaixo o código de uma pequena aplicação de exemplo:


import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.media.AudioClip;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class TocandoAudio extends Application {

 private String AUDIO_URL = getClass().getResource(
   "/audio/top-jamendo.mp3").toString();

 public static void main(String[] args) {
  launch();
 }

 @Override
 public void start(Stage palco) throws Exception {
  AudioClip clip = new AudioClip(AUDIO_URL);// 1
  clip.play(); // 2
  StackPane raiz = new StackPane();
  raiz.getChildren().add(new Text("Tocando Música ")); //3
  Scene cena = new Scene(raiz, 600, 100);
  palco.setTitle("Tocando Audio em JavaFX");
  palco.setScene(cena);
  palco.show();

 }
}
  1. Aqui carregamos o clipe de áudio e informamos a URL do audio a ser tocado;
  2. O áudio irá começar a tocar nessa linha. Semelhante ao vídeo, temos vários outros métodos que poderíamos utilizar
  3. Não é relacionado ao áudio, mas essa linha adiciona um simples texto informativo, pois não temos nada visual quanto tocamos áudio

Conclusão

Tocar conteúdo multimídia usando Java nunca foi tão fácil! Obviamente mostramos aqui a forma mais simples de fazer isso, mas você pode explorar a documentação para criar aplicações mais elaboradas.
Baixe os projetos do Eclipse abaixo(em breve adicionarei os links). As mídias usadas estão dentro de cada projeto, isso deixou os projetos com alguns "megas" a mais. Usamos o vídeo de apresentação do conceito de Creative Commons e o áudio foi o top do Jamendo nesse momento: All I'll Ever Need - Sean Fournier.

18 de jul de 2012

Sua primeira aplicação em JavaFX usando Eclipse

Para aprender como iniciar com o JavaFX 8, vejam esse artigo

Veja um CRUD completo com JavaFX 8!


Nessa primeira postagem vamos mostrar um passo a passo de como executar sua primeira aplicação usando JavaFX 2!
Vamos direto ao assunto, abaixo o que você precisa para seguir esse texto:


  • Eclipse (não há preferência de versão, mas eu irei usar o Indigo para Java EE);
  • Baixe o SDK do JavaFX no site da Oracle.


Ótimo! Já temos tudo o que precisamos. O próximo passo agora é abrir o Eclipse e criar um projeto do tipo Java Project(1). Nesse projeto iremos criar um pacote(2) e nele uma classe Java(3).

  1. Acesse o menu
  2. File -> New -> Java Project, dê um nome (no meu caso ola-javafx) e clique em Finish. 
  3. Clique com o botão direto sobre o seu projeto e acesse o menu New -> Package, dê um nome (no meu caso main) e em seguida clique em Finish.
  4. Clique com o botão direito no pacote main e acesse o menu New -> Class. Dê um nome para a classe (eu usei Main) e clique em Finish.
Agora você deve configurar a biblioteca do JavaFX(1), adicionar o JAR(2) e assim referenciar no seu projeto(3). Uma vez feito isso, todas as classes serão reconhecidas no seu código e você poderá compilar/executar sua aplicação JavaFX

  1. Acesse o menu Windows -> Preferences. Na árvore no lado esquerdo, escolha Java -> Build Path -> User Libraries e clique em New... dê um nome para a biblioteca (eu usei JAVAFX) e clique em OK.
  2. Clique sobre a biblioteca criada e então clique em Add JARs..., navegue até a instalação do JavaFX(no Windows, o SDK deverá ficar em C:\Program Files\Oracle\JavaFX 2.1 SDK) e procure o JAR jfxrt.jar (geralmente na pasta lib). Clique em Ok.
  3. Clique com o botão direito sobre o seu projeto e acesse o menu Build Path -> Add Libraries..., vai aparecer um diálogo. Escolha User Libraries e na tela seguinte marque a recém criada biblioteca do JavaFX e clique em Finish.
Perfeito, agora é hora de código. Nesse primeiro "post" vou simplesmente colar o código aqui e explicar brevemente o mesmo. Veja abaixo o código completo da classe Main e note que temos comentários numerados. Eles marcam os pontos mais importantes do código e explicarei na lista numerada a seguir.

package main;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application { // 1

 public static void main(String[] args) {
  launch(); // 2
 }

 @Override
 public void start(Stage palco) throws Exception { // 3
  StackPane raiz = new StackPane(); // 4
  Label lblMensagem = new Label(); // 5

  lblMensagem.setText("Estou aprendendo JavaFX!"); // 6
  raiz.getChildren().add(lblMensagem); // 7

  Scene cena = new Scene(raiz, 250, 100); // 8
  palco.setTitle("Aprendendo JavaFX"); // 9
  palco.setScene(cena); // 10
  palco.show(); // 11

 }
}
  1. Perceba que a classe principal herda de javafx.application.Application. Toda classe principal de JavaFX deve herdar de Application e implementar o método start;
  2. No método main chamamos o método lunch para começar a nossa aplicação. Aqui não vai código JavaFX, o código vai no método start;
  3. A implementação do método start, herdado da classe Application. O atributo recebido é do tipo Stage. Bruscamente falando, podemos ver o Stage (palco) como o frame, a janela da nossa aplicação, mas na verdade ele não pode ser representado sim se pensarmos nos diversos dispositivos que podem rodar(em um futuro próximo) JavaFX: Celulares, televisores, "tablets", etc;
  4. Nesse ponto nós criamos um elemento chamado "pai", pois permite adicionarmos outras coisas dentro dele. No nosso caso, o StackPane permite adicionar vários elementos os quais tem seu leiaute de pilha, ou seja, eles serão empilhados um sobre o outro. No futuro falaremos mais sobre isso, mas lembre-se que tudo no JavaFX é um nó, ou seja, herda da classe Node;
  5. Não há nada de mais aqui, simplesmente criamos um objeto do tipo Label, que é um controle de interface para mostrar texto. Ponto;
  6. Aqui informamos o texto que o Label irá mostrar. Note que isso poderia ter sido feito pelo construtor, na criação do Label;
  7. Como o StackPane é um elemento pai, ele também tem elementos filhos. Nessa linha de código, recuperamos os filhos dele(getChildren()) e adicionamos nosso Label(add(Node)), fazendo que o Label seja um filho dele;
  8. É hora de aprender outro conceito do JavaFX. Nessa linha criamos uma Scene(cena). Uma cena é o contâiner principal de todos os elementos do JavaFX e na criação dela aproveitamos para informar a raiz (como o nome diz, a raiz de todos os componentes), largura e altura da cena;
  9. Agora vamos voltar a mexer com nosso palco. Nessa linha informamos o título dele, no nosso caso atual, o título da janela que será mostrada;
  10. O palco precisa de uma cena, simplesmente é isso que é feito nessa linha.
  11. Simplesmente mostrando o palco! Se esse método não for chamado, nada irá acontecer quando executar esse código.
Ufa, agora a melhor parte: executar e ver o resultado! Execute[1] o código e deverá ver uma janela como abaixo.
  1. Com a classe Main aberta, simplesmente segure Ctrl e aperte F11.

Conforme pode ver, não é muito difícil usar JavaFX. Ok, pode parecer, mas mais umas 5 aplicações e você já ficará fera nessa nova biblioteca gráfica da plataforma Java. Vou tentar manter um post por semana e esse mesmo estilo de tutorial, espero ter agradado vocês!