TableView Cell Factories

GitHub repo (app4)

This post is about TableView factories, and the difference between Cell Factories and Cell Value Factories. There are a few good blog posts about this topic – I am just going to discuss the key concepts and the Kotlin version using Java 11.

CellValueFactories or CellFactories?

A cellValueFactory tells the column which values from the TableView contained type to display in the cells for each row.

A cellFactory tells the column how to display the data as a string.

Simplest Scenario  – Column Represents Object’s String Property

  • Cell Value Factory Required – No
  • Cell Factory Required – No

A lot of the time, you just want to display an object’s string property. This can be done with the PropertyValueFactory:

dateObjectColumn.cellValueFactory = PropertyValueFactory<DateItem, OffsetDateTime>("date")

Simple Object Scenario – Column Represents Object Property And Default toString() is Good Enough 

  • Cell Value Factory Required – No
  • Cell Factory Required – No

Here, the column represents an object, but you are happy that its default string representation is what you want. So, no need for any factories – PropertyValueFactory is good enough.

dateObjectColumn.cellValueFactory = PropertyValueFactory<DateItem, OffsetDateTime>("date")

Realistic Object Scenario – Column Represents a Complex Object

  • Cell Value Factory Required – Maybe
  • Cell Factory Required – Yes

The column maps to an object, but you need to specify which property to use, and you want to specify how the data appears on the screen. This may or may not require a cell value factory.

Dates are a common example – often you want to format dates in a specific way.

The code would look like this in the simpler scenario, without a cell value factory:

dateCustomColumn.cellValueFactory = PropertyValueFactory<DateItem, OffsetDateTime>("date") 
dateCustomColumn.cellFactory = ModifiedISODateCellFactory() 

And with a cell value factory: 

dateCustomColumn.cellValueFactory = DateCellValueFactory() 
dateCustomColumn.cellFactory = ModifiedISODateCellFactory()

Realistic Object Scenario – Lambda Version

The previous version used classes for the factory declarations, but lambdas work as well.

dateLambdaColumn.setCellValueFactory { cell: TableColumn.CellDataFeatures<DateItem, OffsetDateTime> -> ReadOnlyObjectWrapper(cell.value.date) } 

dateLambdaColumn.setCellFactory { 
   object : TableCell<DateItem, OffsetDateTime>() { 
      public override fun updateItem(dt: OffsetDateTime?, empty: Boolean) { 
         super.updateItem(dt, empty) 
         if (!empty) 
            this.text = "Lambda - $dt" 
      } 
   }
}

Last Comments

Table columns are pretty straightforward, once you understand how the factories work. There is a complete demo application demonstrating the scenarios discussed about here – see this on how to setup and run app4.