Thursday 19 January 2012

Scala, JavaFX, TableColumns

In my previous post we created a bunch of columns using the following code:
val maxMemColumn = new TableColumn[MyTableRow, Long]("Max")
maxMemColumn.setCellValueFactory(new PropertyValueFactory[MyTableRow, Long]("maxMem"))
It would be nice to abstract this call, create a template for it. Looking at the TableColumn API, another way to bind a cell to an object value is to use setCellValueFactory on the TableColumn:
firstNameCol.setCellValueFactory(new Callback, ObservableValue>() {
  public ObservableValue call(CellDataFeatures p) {
    // p.getValue() returns the Person instance for a particular TableView row
	return p.getValue().firstNameProperty();
  }
});
Note that firstNameProperty is of type ObservableValue. We can therefore remove all the other properties from MyTableRow and just leave the ones which are of type ObservableValue... We are then left with:
sealed class MyTableRow2 {
  val totMem = new SimpleLongProperty(0L)
  val maxMem = new SimpleLongProperty(0L)
  val freeMem = new SimpleLongProperty(0L)
  val usedMem = new SimpleLongProperty(0L)
}
Now, let's try to write a generic create column Scala function (newCol_2 below):
private def newCol_2[R, V](displayName: String, get: (R) => ObservableValue[V]): TableColumn[R, V] = {
  val column = new TableColumn[R, V](displayName)
  column.setCellValueFactory(new Callback[CellDataFeatures[R, V], ObservableValue[V]] {
    override def call(p: CellDataFeatures[R, V]) : ObservableValue[V] = get(p.getValue())
  })
  column
}
the columns are now initialised like this:
val maxMemColumn = newCol_2("Max", {r:MyTableRow2 => r.maxMem})
val totalMemColumn = newCol_2("Tot", {r:MyTableRow2 => r.totMem})
val freeMemColumn = newCol_2("Free", {r:MyTableRow2 => r.freeMem})
val usedMemColumn = newCol_2("Used", {r:MyTableRow2 => r.usedMem})

No comments:

Blog Archive