trilogy
trilogy

Reputation: 1795

JavaFX TableView Properties showing null

How do I make SimpleIntegerProperty show up as blank (null)? SimpleStringProperty allows nulls to show up as blank, but SimpleIntegerProperty does not. I don't really want to use SimpleStringProperty in place of it because sorting doesn't really work properly if you view numbers as Strings...

Upvotes: 0

Views: 879

Answers (1)

Zephyr
Zephyr

Reputation: 10253

Here is a very simple example application to demonstrate how to do this. Basically, you will override the updateItem() method of the cell to provide an empty cell if the value of your IntegerProperty is 0.

Item.java:

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Item {
    private final StringProperty name = new SimpleStringProperty();
    private final IntegerProperty quantity = new SimpleIntegerProperty();

    public Item(String name, int qty) {
        this.name.set(name);
        this.quantity.set(qty);
    }

    public String getName() {
        return name.get();
    }

    public StringProperty nameProperty() {
        return name;
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public int getQuantity() {
        return quantity.get();
    }

    public IntegerProperty quantityProperty() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity.set(quantity);
    }
}

Main.java:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Simple TableView
        TableView<Item> tableView = new TableView<>();
        TableColumn<Item, String> colName = new TableColumn<>("Name");
        TableColumn<Item, Number> colQuantity = new TableColumn<>("Quantity");
        // Since IntegerProperty implements ObservableValue<Number> instead of Integer, for some reason, we need
        // to change our column definition to accept that

        // Set the cell value factories
        colName.setCellValueFactory(c -> c.getValue().nameProperty());
        colQuantity.setCellValueFactory(c -> c.getValue().quantityProperty());

        // Override the CellFactory for quantity to leave empty if value is 9
        colQuantity.setCellFactory(param -> new TableCell<Item, Number>() {
            @Override
            protected void updateItem(Number itemQuantity, boolean empty) {
                super.updateItem(itemQuantity, empty);
                if (empty || itemQuantity.equals(0)) {
                    // If the item's quantity is 0, set the cell to display nothing (null)
                    setText(null);
                } else {
                    // Otherwise, the cell should display a label with the value of the item's quantity
                    setText(itemQuantity.toString());

                }
            }
        });

        // Add the columns to the TableView
        tableView.getColumns().addAll(colName, colQuantity);

        // Populate the table with sample items
        tableView.getItems().setAll(
                new Item("Tools", 3),
                new Item("Saws", 0),
                new Item("Ruler", 2)
        );

        root.getChildren().add(tableView);

        // Show the Stage
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

The Result:

screenshot

EDIT

I changed the CellValueProperty for each cell to use the Item properties instead of reflection. Since the IntegerProperty implements ObservableValue<Number> instead of ObservableValue<Integer> for some reason, I did also change the definition of colQuantity to use the Number type.

Upvotes: 3

Related Questions