Почему первая TableRow пуста в моем CellFactory? - PullRequest
1 голос
/ 13 апреля 2019

У меня есть рабочая реализация DatePicker TableCell, но у меня NullPointerException, когда мои CellFactory пытаются получить TableRow.

Исключение не появляетсяповлиять на реальную функциональность каким-либо образом, но я не понимаю, что ее вызывает.

Для краткости, здесь только реализация CellFactory (полный MCVE ниже, но, возможно, этого достаточно, чтобы вы могли увидетьмоя ошибка):

    colDatePaid.setCellFactory(col -> new TableCell<Bill, LocalDate>() {

        final DatePicker datePicker = new DatePicker();

        @Override
        protected void updateItem(LocalDate item, boolean empty) {
            super.updateItem(item, empty);

            if (empty) {
                setGraphic(null);
            } else {

                System.out.println(getTableRow()); // <-- This prints 'null' only once upon execution
                Bill bill = (Bill) getTableRow().getItem();

                if (item == null || bill.isDateChanged()) {
                    bill.datePaidProperty().bind(datePicker.valueProperty());
                    setGraphic(datePicker);
                } else {
                    setGraphic(new Label(bill.getDatePaid().toString()));
                }

            }
        }
    });

Метод println() дает следующий вывод, а также NPE:

null
TableRow@47e536dc[styleClass=cell indexed-cell table-row-cell]'null'
TableRow@1345fc2c[styleClass=cell indexed-cell table-row-cell]'null'
TableRow@44dfbc27[styleClass=cell indexed-cell table-row-cell]'null'
TableRow@5c091f1[styleClass=cell indexed-cell table-row-cell]'null'
TableRow@3b50e9f5[styleClass=cell indexed-cell table-row-cell]'null'
TableRow@17a393fb[styleClass=cell indexed-cell table-row-cell]'null'

Как я уже говорил, работа приложения делаетне похоже, что это затронуто, но мне нужна помощь в решении этой конкретной проблемы.

Полный MCVE:

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.time.LocalDate;

public class ConditionalColumnSample extends Application {

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

    @Override
    public void start(Stage primaryStage) {

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

        // TableView
        TableView<Bill> tableView = new TableView<>();
        TableColumn<Bill, Number> colAmountDue = new TableColumn<>("Amount Due");
        TableColumn<Bill, LocalDate> colDatePaid = new TableColumn<>("Date Paid");
        tableView.getColumns().addAll(colAmountDue, colDatePaid);

        tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        // CellValueProperties
        colAmountDue.setCellValueFactory(tf -> tf.getValue().amountDueProperty());
        colDatePaid.setCellValueFactory(tf -> tf.getValue().datePaidProperty());

        // CellFactory for Date Paid column
        colDatePaid.setCellFactory(col -> new TableCell<Bill, LocalDate>() {

            final DatePicker datePicker = new DatePicker();

            @Override
            protected void updateItem(LocalDate item, boolean empty) {
                super.updateItem(item, empty);

                if (empty) {
                    setGraphic(null);
                } else {

                    System.out.println(getTableRow()); // <-- This prints 'null' only once upon execution
                    Bill bill = (Bill) getTableRow().getItem();

                    if (item == null || bill.isDateChanged()) {
                        bill.datePaidProperty().bind(datePicker.valueProperty());
                        setGraphic(datePicker);
                    } else {
                        setGraphic(new Label(bill.getDatePaid().toString()));
                    }

                }
            }
        });

        // Button to test data
        Button button = new Button("Print Values");
        button.setOnAction(event -> {
            for (Bill bill : tableView.getItems()) {
                System.out.println(bill);
            }
        });

        // Sample data
        tableView.getItems().addAll(
                new Bill(42.34, null),
                new Bill(894.99, null),
                new Bill(54.87, LocalDate.now()),
                new Bill(5.00, null),
                new Bill(123.68, LocalDate.of(2019, 12, 25))
        );

        root.getChildren().addAll(tableView, button);

        // Show the stage
        primaryStage.setScene(new Scene(root));
        primaryStage.setTitle("Sample");
        primaryStage.show();
    }
}

class Bill {

    private DoubleProperty amountDue = new SimpleDoubleProperty();
    private ObjectProperty<LocalDate> datePaid = new SimpleObjectProperty<>();

    private BooleanProperty dateChanged = new SimpleBooleanProperty();

    public Bill(double amountDue, LocalDate datePaid) {
        this.amountDue.set(amountDue);
        this.datePaid.set(datePaid);

        // Listener to determine if the date has been changed
        this.datePaidProperty().addListener((observable, oldValue, newValue) -> {
            dateChanged.set(true);
        });

    }

    public double getAmountDue() {
        return amountDue.get();
    }

    public void setAmountDue(double amountDue) {
        this.amountDue.set(amountDue);
    }

    public DoubleProperty amountDueProperty() {
        return amountDue;
    }

    public LocalDate getDatePaid() {
        return datePaid.get();
    }

    public void setDatePaid(LocalDate datePaid) {
        this.datePaid.set(datePaid);
    }

    public ObjectProperty<LocalDate> datePaidProperty() {
        return datePaid;
    }

    public boolean isDateChanged() {
        return dateChanged.get();
    }

    public void setDateChanged(boolean dateChanged) {
        this.dateChanged.set(dateChanged);
    }

    public BooleanProperty dateChangedProperty() {
        return dateChanged;
    }

    @Override
    public String toString() {
        return "Bill{" +
                "amountDue=" + amountDue +
                ", datePaid=" + datePaid +
                ", dateChanged=" + dateChanged +
                '}';
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...