Skip to content

Change custom cellFactory assignment methods to help in correct implementation that avoids artifacts #256

Closed

Description

@jpsacha

JavaFX requires that custom cell factories are implemented in such a way that javafx.scene.control.Cell[T]#updateItem(T item, boolean empty) is implemented correctly. Quite from JavaFX documentation for updateItem:

It is very important that subclasses of Cell override the updateItem method properly, as failure to do so will lead to issues such as blank cells or cells with unexpected content appearing within them.

Current implementation of helper cellFactory assignment is not suitable to handle that. Consider TreeCell#cellFactory_=(v: (TreeView[T] => TreeCell[T])). Current suggestions is to use it like this:

cellFactory = (v: TreeView[Person]) => new TreeCell[Person] {
  treeItem.onChange { (_, _, p) =>
    text = if (p != null) p.value().firstName + " " + p.value().lastName else null
    graphic = null
  }
}

Above implementation will results in rendering artifacts as empty cells cannot be handled correctly, the empty flag is not available. The proper way would be to extends 'javafx.scene.control.Cell':

cellFactory = _ =>
  new javafx.scene.control.TreeCell[Person] {

  // We are deriving from JavaFX, for easier use add ScalaFX wrapper for  `this`
  val self: TreeCell[Person] = this

  override def updateItem(item: Person, empty: Boolean): Unit = {
     super.updateItem(item, empty)
     self.graphic = null
     self.text =
       if (empty) 
         null
       else item match {
         case p: Person => p.firstName + " " + p.lastName
         case null => null
       }
   }
 }

This is a lot of boilerplate code. There should be a helper cellFactory assignment that would promote ability to write correct code. Mot of the boilerplate would be generated automatically, user would only handle rendering and be provided with empty flag. Consider assignment with signature:

def cellFactory_=(u: ((TreeCell[T], T, Boolean) => Unit))

It would be used like this:

        cellFactory = (treeCell, item, empty) => {
          treeCell.graphic = null
          treeCell.text =
            if (empty)
              null
            else
              item match {
                case p: Person => item.firstName + " " + item.lastName
                case null => null
              }
        }

Maybe it should be even simpler. Code for resetting graphic and text when item is null or empty would be generated automatically. A cell factory would only handle non-null items and non-empty cells:

        cellFactory = (treeCell, item) => {
          treeCell.text =  item.firstName + " " + item.lastName
        }

This would be for all classes that have cell factories, not only TreeView.

Activity

  1. added this to the 8.0.*-R12 milestone on Nov 27, 2016
  2. self-assigned this
    on Nov 30, 2016
  3. objektwerks commented on Mar 18, 2017

    @objektwerks

    I finally found an interim solution based on this code: https://groups.google.com/forum/#!topic/scalafx-users/b3d6y3RHao0 That said, I look forward to a clean cell factory impl for ComboBox, ListView and the like.

  4. modified the milestones: 8.0.*-R12, 8.0.*-R13 on Oct 15, 2017
  5. modified the milestones: 8.0.*-R13, 8.0.*-R14 on Sep 30, 2018
  6. modified the milestones: 8.0.*-R14, 12-R18 on Apr 28, 2019
  7. modified the milestones: 12-R18, 12-R19 on Sep 6, 2019
  8. changed the title [-]Change custom `cellFactory` assignment methods to help in correct implementation that avoids artifacts[/-] [+]Change custom `cellFactory` assignment methods to help in correctly implementation that avoids artifacts[/+] on Jan 29, 2020
  9. 15 remaining items

  10. modified the milestones: Backlog, 16.0.0-R25 on May 19, 2021
  11. added 6 commits that reference this issue on May 19, 2021
  12. added 4 commits that reference this issue on Jun 8, 2021
  13. added 2 commits that reference this issue on Sep 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions