24 de abr de 2014

Usando Tabelas com JavaFX: TableView

Um dos controles mais utilizados em aplicações cotidianas é a Tabela. Com controles que permitam visualizar dados em forma de tabelas podemos mostrar: lista de funcionários, de produtos, dados já ordenados em planilhas, informações diversas que vêm de algum servidor.
Nesse aspecto, estamos bem "servidos" com o TableView do JavaFX. A TableView, juntamente com a classe TableColumn, facilita visualizações de dados em uma aplicação JavaFX.
Nesse artigo, iremos mostrar o básico sobre criação de tabelas usando JavaFX.

Visão geral da classe TableView 

TableView é mais um controle de interface. Para começarmos falando dela, veja a seguinte imagem:



Uma tabela tem colunas e linhas. Quando configuramos as colunas de uma TableView, temos que também dizer como cada coluna vai representar os dados da tabela.

Itens

Os dados devem ser do tipo da declaração da tabela. Por exemplo, se declaramos uma tabela usando:

TableView<Pessoa> tabela = new TableView<>();

A tabela só irá aceitar dados do tipo Pessoa: 

List<Pessoa> pessoas = ....
tabela.setItems(FXCollections.observableArrayList(pessoas));

Caso você tente inserir dados de outro tipo, simplesmente você terá um erro de compilação.

Colunas

As colunas são definidades pela classe TableColumn e devem saber lidar com cada linha da tabela. Isso é feito através de fábricas de células, que são classes que recebem cada item da tabela e retornam uma célula da tabela. A fábrica você deve fornecer ou usar algumas colunas que já sabem fabricar as células de um tipo já conhecido. Veja um exemplo onde criamos colunas para as propriedades nome, idade e email de uma pessoa:

TableColumn<Pessoa, String> colunaNome = new TableColumn<>("Nome");
TableColumn<Pessoa, String> colunaIdade = new TableColumn<>("Idade");
TableColumn<Pessoa, String> colunaEmail = new TableColumn<>("E-mail");
tabela.getColumns().addAll(colunaNome, colunaIdade, colunaEmail);

Por exemplo, para acessar as propriedades do objeto Pessoa, podemos usar uma fábrica pronta, a PropertyValueFactory. Abaixo criamos as fábricas para as propriedades (atributos) da classe pessoa, note a String que ele recebe no construtor que é o nome da propriedade que declaramos na classe:

colunaNome.setCellValueFactory(new PropertyValueFactory<>("nome"));
colunaIdade.setCellValueFactory(new PropertyValueFactory<>("idade"));
colunaEmail.setCellValueFactory(new PropertyValueFactory<>("email"));

Um exemplo completo de uso da TableView

Abaixo temos um código simples que mostra como mostrar uma lista de pessoas em uma TableView. Veja que não é nada sofisticado, mas com esse código, você já estará apto a construir suas próprias aplicações que usam tabelas.

import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;

/**
 *
 * @author william
 */
public class Post13Tabelas extends Application {

    @Override
    public void start(Stage primaryStage) {
        List pessoas = Arrays.asList(
                new Pessoa("William", 32, "william@email.com"),
                new Pessoa("Luana", 17, "luana@email.com"),
                new Pessoa("Maria", 12, "maria@email.com"),
                new Pessoa("João", 15, "joao@email.com"),
                new Pessoa("Antônio", 28, "antonio@email.com"),
                new Pessoa("Teles", 17, "teles@email.com"),
                new Pessoa("Eduan", 30, "eduan@email.com"),
                new Pessoa("Gabu", 22, "gabu@email.com")
        );

        TableView tabela = new TableView<>();
        TableColumn colunaNome = new TableColumn<>("Nome");
        TableColumn colunaIdade = new TableColumn<>("Idade");
        TableColumn colunaEmail = new TableColumn<>("E-mail");

        colunaNome.setCellValueFactory(new PropertyValueFactory<>("nome"));
        colunaIdade.setCellValueFactory(new PropertyValueFactory<>("idade"));
        colunaEmail.setCellValueFactory(new PropertyValueFactory<>("email"));

        tabela.setItems(FXCollections.observableArrayList(pessoas));
        tabela.getColumns().addAll(colunaNome, colunaIdade, colunaEmail);
        
        primaryStage.setScene(new Scene(tabela));
        primaryStage.setWidth(250);
        primaryStage.setHeight(300);
        primaryStage.setTitle("Tabelas no JavaFX");
        primaryStage.show();
    }

    public static class Pessoa {

        private String nome;
        private int idade;
        private String email;

        public Pessoa(String nome, int idade, String email) {
            this.nome = nome;
            this.idade = idade;
            this.email = email;
        }

        public String getNome() {
            return nome;
        }

        public void setNome(String nome) {
            this.nome = nome;
        }

        public int getIdade() {
            return idade;
        }

        public void setIdade(int idade) {
            this.idade = idade;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

    }
}


Conclusão

Nesse breve artigo nós mostramos como criar tabelas em JavaFX. Claro que o tópico é extenso e podemos voltar ao tópico no futuro.

Nosso código agora é usando Java 8 e Netbeans 8.  Veja o código no github.

15 de abr de 2014

Escrevendo aplicações JavaFX 8 usando Javascript

Uma das novidades mais legais do Java 8 é a nova engine javascript chamada "Nashorn". Com ela podemos escrever aplicações inteiras que usam JavaFX com a linguagem Javascript.
Hoje vamos mostrar aplicações simples para introduzir e apresentar esse conceito. Lembre que estamos usando a mais nova versão do Java, o Java 8.

* É requerido ter feito pelo menos o "Olá mundo" do JavaFX para seguir nessa postagem

Carregando javascript a partir do Java

Através de sua aplicação, você pode colocar variáveis visíveis para o Javascript e do seu código Java chamar Javascript. O código abaixo é uma aplicação JavaFX que usa a engine para colocar o Stage principal no escopo do script Javascript e então chamamos um script do nosso sistema de arquivos com o resto do código da view:

import javafx.application.Application;
import javafx.stage.Stage;
import javax.script.*;
import java.io.FileReader;

public class CarregaJS extends Application{

        @Override
        public void start(Stage stage){
                try{
                        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
                        engine.put("stage", stage);
                        engine.eval(new FileReader("/opt/helloJavaFX.js"));
                }catch(Exception e){ 
                        e.printStackTrace();
                }   
        }   
 }


Veja o uso da classe ScriptEngineManager para carregar a engine do Nashorn. Logo, carregamos o conteúdo do arquivo em um FileReader e interpretamos o script usando o método eval, mas antes disso colocamos o objeto stage no escopo do Javascript. Veja como ficou nosso script:


var txtOla = new javafx.scene.control.Label(">> Olá Mundo! <<")
txtOla.font = new javafx.scene.text.Font(50)
stage.scene = new javafx.scene.Scene(txtOla)
stage.width = 500 
stage.title = "Olá JavaFX + Javascript"
stage.show()


Note que se você quiser alterar a view, você simplesmente pode modificar o script sem ter que recompilar o seu código Java! Resultado:


Carregando scripts usando a linha de comando

É possível usar a ferramenta jjs e escrever somente javascript. Para JavaFX especificamente, há um parâmetro que, quando usado, o Nashorn irá colocar uma variável chamada $STAGE para ser usada no seu script. Ela representa o stage principal da sua aplicação. Veja um "Olá Mundo" com Javascript:

var txtOla = new javafx.scene.control.Label(">> Olá Mundo! <<")
txtOla.font = new javafx.scene.text.Font(50)
$STAGE.scene = new javafx.scene.Scene(txtOla)
$STAGE.width = 500 
$STAGE.title = "Olá JavaFX + Javascript"
$STAGE.show()


Para executar ele, tenha o JDK 8 instalado e no seu "path", ou navegue até o diretório $JAVA_HOME/bin/ e encontre o executável do jjs e execute o seguinte comando:

$ jjs -fx helloJavaFX.js

Esse script produz o mesmo resultado do código anterior.

Conclusão

Com Java 8 temos uma nova alternativa para escrever aplicações. Claro que o "Olá Mundo" é só o começo, mas teríamos que explorar a nova engine e sua compatibilidade com as APIs Java para construirmos grandes aplicações.
Caso você não queira escrever Java, nem Javascript, lembre-se que você poderá usar FXML e a ferramenta Scene Builder.

O código Javascript do Olá mundo está no github