user3346601
user3346601

Reputation: 1049

Custom Cells in TableView

I'm working on a scalafx project and I'd like a TableView where some of the Cells contain a button. I've found an example of how to put a graphic inside of a tablecell. When I use example and only replace the call to graphic = ... to use a button I will sometimes get Cells where every column is empty except the one whith the button:

screenshot

How do i fix this? (I've checked that it's not just an empty string on the name value, so that last login button should not be there)

Here is the code from the example modified to use a button:

new TableColumn[Person, String] {
        text = "Login"
        cellValueFactory = { _.value.favoriteColor }
        cellFactory = { _ =>
          new TableCell[Person, String] {
            item.onChange { (_, _, newColor) =>
              graphic = new Button {
                text = "Login"
                onAction = {
                  (e: ActionEvent) => println("pressed the button")
                }
              }
            }
          }
        }
}

Upvotes: 1

Views: 1026

Answers (2)

user3346601
user3346601

Reputation: 1049

Heres James_D's answer in scala:

new TableColumn[Person, String] {
  text = "Login" 
  cellValueFactory = { _.value.name } //it actually doesn't matter which value you choose here
  cellFactory = { _ =>
    val cell = new TableCell[Person, String]()
    val btn = new Button {
      text = "Login"
      onAction = { (e: ActionEvent) =>
        println("Button pressed")
      }
    }
    cell.setContentDisplay(ContentDisplay.GRAPHIC_ONLY)

    cell.itemProperty().addListener(new ChangeListener[String] {
      override def changed(obs: ObservableValue[_ <: String], oldItem: String, newItem: String): Unit = {
        if (newItem == null) {
          cell.setGraphic(null)
        } else {
          cell.setGraphic(btn)
        }
      }
    })

    cell
  }
}

Upvotes: 0

James_D
James_D

Reputation: 209724

(Caveat: I'm not a Scala programmer, so I can only answer this from a JavaFX perspective. You should be able to translate this to Scala though.)

You need to check whether the TableCell is empty, and set the graphic to null if the cell is empty, and to the button otherwise.

Additionally, it's not a good idea to create a new button every time the item changes (which can be quite frequently); you should instead create it once when a new cell is created (which is rare) and then just set it (or null) as the graphic when the item changes.

In Java 8 the code looks like this:

TableColumn<Person, String> column = new TableColumn<>("Login");
column.setCellValueFactory(data -> data.getValue().favoriteColorProperty());

column.setCellFactory( col -> {

    TableCell<Person, String> cell = new TableCell<>();

    Button button = new Button("Login");
    button.setOnAction(event -> {
        System.out.println("pressed the button");
        // you can call cell.getItem() if you want to do something specific for this cell
    });

    cell.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);

    cell.itemProperty().addListener((obs, oldItem, newItem) -> {
        if (newItem == null) {
            cell.setGraphic(null);
        } else {
            cell.setGraphic(button);
        }
    });

    return cell ;
});

Here I am assuming the item is only ever null for empty cells: if this is not the case you need to either subclass TableCell and override the updateItem(...) method, or observe both the itemProperty() and the emptyProperty() of a default TableCell.

Upvotes: 1

Related Questions