为什么第一个TableRow在我的CellFactory中为空?

时间:2019-04-12 23:14:26

标签: javafx

我有一个DatePicker TableCell的有效实现,但是当我的NullPointerException尝试检索CellFactory时,我遇到了TableRow。 / p>

该异常似乎不会以任何方式影响实际功能,但我不知道是什么原因造成的。

为简便起见,这只是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 +
                '}';
    }
}

0 个答案:

没有答案