Usando TableView
Autor: Jean Paul Lopes | Publicado: 2011-07-05T12:17:00-07:00

Um dos grandes componentes visuais incorporados no JavaFX 2.0 (esteve em preview no 1.3) foi o TableView.

Ele oferece um grande suporte na apresentação de dados em formato de tabela, desde uma apresentação standard até uma customização total de cada célula.

Inicialmente temos que ter em mente que uma tabela é formada de linhas e colunas e que cada intersecção entre elas forma uma célula.

Por definição um TableView do JavaFX tem como fonte de dados para sua formação um ObservableList de objetos com uma estrutura específica, que eu chamo de vulgarmente de JavaFxBean. Um JavaFxBean tem uma estrutura próxima aos JavaBeans, porém seus atributos são descendentes (extensões) da interface javafx.beans.Property (StringProperty, IntegerProperty, BooleanProperty, ObjectProperty). Segundo a documentação da API 2.0 ele tem este formato:
public class Person {
private StringProperty firstName;
public void setFirstName(String value) { firstName.set(value); }
public String getFirstName() { return firstName.get(); }
public StringProperty firstNameProperty() { 
if (firstName == null) firstName = new StringProperty();
return firstName; 
}

private StringProperty lastName;
public void setLastName(String value) { lastName.set(value); }
public String getLastName() { return lastName.get(); }
public StringProperty lastNameProperty() { 
if (lastName == null) lastName = new StringProperty();
return lastName; 
} 
}
No meu exemplo uso uma classe JPA TbTlmkChamada que é recuperada pela classe TbTlmkChamadaJpaController. Como o JPA só permite a criação de atributos de tipos específicos (nos quais os descendentes de Property não se encaixam) criei uma classe (Proxy) TbTlmkChamadaFxBean, a fim de receber os objetos do banco. Esta classe simplesmente possui os mesmos atributos da classe original, mas com tipos descendentes de javafx.beans.Property. 

Bem ainda não chegamos ao TableView. A hora é agora.

Para uma visualização básica, podemos criar um TableView padrão com o seguinte formato:

TbTlmkChamadaJpaController control = new TbTlmkChamadaJpaControllerImpl(telemarketingserver.TelemarketingServer.emf); 

tabela = new TableView();
List&lt;TbTlmkChamada&gt; findTbTlmkChamadaEntities = control.findTbTlmkChamadaEntities();

List&lt;TbTlmkChamadaFxBean&gt; lista = new ArrayList&lt;TbTlmkChamadaFxBean&gt;();
for (int i=0;i &lt; TbTlmkChamadaEntities.size();i++) {
lista.add(new TbTlmkChamadaFxBean(findTbTlmkChamadaEntities.get(i)));
}
ObservableList&lt;TbTlmkChamadaFxBean&gt; chamadas = FXCollections.observableList(lista);
tabela.setItems(chamadas);
TableColumn&lt;Integer&gt; codigoCol = new TableColumn&lt;Integer&gt;("Código");
codigoCol.setProperty("codigo");
TableColumn&lt;String&gt; dadosCol = new TableColumn&lt;String&gt;("Dados");
dadosCol.setProperty("dados");
TableColumn&lt;Date&gt; dataCol = new TableColumn&lt;Date&gt;("Data");
dataCol.setProperty("proxChamada");

final TableColumn&lt;TbTlmkFila&gt; filaCol = new TableColumn&lt;TbTlmkFila&gt;("Fila");
filaCol.setProperty("fila");


tabela.getColumns().addAll(codigoCol,dadosCol,filaCol,dataCol);
tabela.setPrefWidth(800);
getChildren().add(tabela);que vai resultar em uma tabela como esta:


Como se percebe foram colocados as colunas segundo os atributos da classe TbTlmkChamadaFxBean (usando os seus respectivos métodos toString()).

Agora é possível enriquecer o funcionamento desta tabela. Incialmente a ordenação das linhas (no exemplo pela coluna Código):

codigoCol.setComparator(new Comparator() {

@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});Com estas linhas de código setamos o comparador utilizado pela coluna codigoCol para compara o valor dos objetos.

também é possível modificar o conteúdo visível de cada célula, como no código a seguir:
filaCol.setCellFactory(new Callback&lt;TableColumn&lt;TbTlmkFila&gt;, TableCell&lt;TbTlmkFila&gt;&gt;() {

@Override
public TableCell&lt;TbTlmkFila&gt; call(TableColumn&lt;TbTlmkFila&gt; param) {
TableCell&lt;TbTlmkFila&gt; cell = new TableCell&lt;TbTlmkFila&gt;() {
@Override public void updateItem(TbTlmkFila value, boolean empty) {
super.updateItem(value, empty);

if (empty) {
setNode(null);
} else {
VBox vbox = new VBox(5);
vbox.getChildren().add(new Label(value.getNome()));
vbox.getChildren().add(new Label(value.getCliente().getNome()));
vbox.setStyle("-fx-background-color:#FF0000;");
setNode(vbox);
}
}
};
return cell;



}
});
Usando o método setCellFactory é possível criar CellFactory´s customizados para cada uma das colunas. O que não é muito bem documento na API javaFX 2.0 é como se acessa o valor do objeto referente a célula. Isto é feito através da sobre escrita do método updateItem. Dentro deste método é onde é definido o que será apresentado em cada célula.

O resultado deste código é a seguinte tabela:

Como o resultado do cellFactory de uma coluna é um objeto da classe Node, a imaginação dos desenvolvedores é limite do que é possível ser apresentado em uma célula: Region´s, ListView´s, Button´s, outros TableView´s. As posibilidades são infinitas.

Espero que este post possa ser útil a alguém como foi para mim.

Bom código a todos.