如果列包含特定值,则 JavaFX TableView 更改列数据

JavaFX TableView change column data if column contains certain value

如果某行的首剂预约日期是 0000-01-01,我想在 tableview 的哪个位置显示它,那么它将显示 N/A 而不是 0000-01- 01 对于那个特定的行,但是因为我已经将 fDoseDateColumn 声明为 ,我不知道如何为它分配一个字符串类型“N/A”,所以我试图找到方法来做到这一点.

这些是这个场景的代码:

@SuppressWarnings("unchecked")
public void ViewAllRecipientData(Stage stage, GridPane gridPane, ObservableList<Recipient> recipient, ObservableList<Center> center){
    recipientTableView = new TableView<Recipient>();
    gridPane.add(allRecipientDataLabel, 0, 0, 4, 1);
    gridPane.add(recipientTableView, 0, 1, 4, 1);
    gridPane.add(selectCenterLabel, 0, 3);
    gridPane.add(centerChoice, 1, 2, 1, 3);
    gridPane.add(assignButton, 2, 2, 1, 3);
    gridPane.add(selectAllCheckBox, 0, 4);
    gridPane.add(backButton, 3, 2, 1, 3);
    allRecipientDataLabel.setFont(titleFont);
    GridPane.setHalignment(allRecipientDataLabel, HPos.CENTER);
    GridPane.setHalignment(selectAllCheckBox, HPos.CENTER);
    GridPane.setHalignment(selectCenterLabel, HPos.CENTER);
    recipientTableView.setPrefSize(1366, 600);
    assignButton.setPrefSize(265, 70);
    backButton.setPrefSize(265, 70);
    centerChoice.setPrefSize(705, 70);

    TableColumn<Recipient, CheckBox> selectColumn = new TableColumn<>("Select");
    TableColumn<Recipient, Integer> idColumn = new TableColumn<>("ID");
    TableColumn<Recipient, String> nameColumn = new TableColumn<>("Name");
    TableColumn<Recipient, Integer> ageColumn = new TableColumn<>("Age");
    TableColumn<Recipient, String> phoneColumn = new TableColumn<>("Phone");
    TableColumn<Recipient, String> centerColumn = new TableColumn<>("Assigned Center");
    TableColumn<Recipient, String> fDoseStatusColumn = new TableColumn<>("First Dose Status");
    TableColumn<Recipient, LocalDate> fDoseDateColumn = new TableColumn<>("First Dose Appointment Date");
    TableColumn<Recipient, String> fDoseBatchColumn = new TableColumn<>("First Dose Batch Number");
    TableColumn<Recipient, String> sDoseStatusColumn = new TableColumn<>("Second Dose Status");
    TableColumn<Recipient, LocalDate> sDoseDateColumn = new TableColumn<>("Second Dose Appointment Date");
    TableColumn<Recipient, String> sDoseBatchColumn = new TableColumn<>("Second Dose Batch Number");
    
    selectColumn.setCellValueFactory(new PropertyValueFactory<>("select"));
    idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
    nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
    ageColumn.setCellValueFactory(new PropertyValueFactory<>("age"));
    phoneColumn.setCellValueFactory(new PropertyValueFactory<>("phone"));
    centerColumn.setCellValueFactory(new PropertyValueFactory<>("center"));
    fDoseStatusColumn.setCellValueFactory(new PropertyValueFactory<>("fDoseStatus"));
    fDoseDateColumn.setCellValueFactory(new PropertyValueFactory<>("fDoseDate"));
    fDoseBatchColumn.setCellValueFactory(new PropertyValueFactory<>("fDoseBatch"));
    sDoseStatusColumn.setCellValueFactory(new PropertyValueFactory<>("sDoseStatus"));
    sDoseDateColumn.setCellValueFactory(new PropertyValueFactory<>("sDoseDate"));
    sDoseBatchColumn.setCellValueFactory(new PropertyValueFactory<>("sDoseBatch"));
    selectColumn.setStyle( "-fx-alignment: CENTER");

    for(int i = 0; i < recipient.size(); i++){
        recipient.get(i).initialiseCheckBox();
    }
    recipientTableView.setItems(recipient);
    
    recipientTableView.getColumns().addAll(selectColumn, idColumn, nameColumn, ageColumn, phoneColumn, centerColumn, fDoseStatusColumn, fDoseDateColumn, fDoseBatchColumn, sDoseStatusColumn, sDoseDateColumn, sDoseBatchColumn);

    centerChoice.getItems().clear();
    centerChoice.getItems().add("N/A");
    centerChoice.setValue("N/A");
    for(int i = 0; i < center.size(); i++){
            centerChoice.getItems().add(center.get(i).getName());
    }

    selectAllCheckBox.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent arg0) {
            if(selectAllCheckBox.isSelected()){
                for(int i=0; i<recipient.size(); i++){
                    recipient.get(i).getSelect().setSelected(true);
                }
            }
            else{
                for(int i=0; i<recipient.size(); i++){
                    recipient.get(i).getSelect().setSelected(false);
                }
            }
        }    
    }); 

    assignButton.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent arg0) {
            Boolean assignSuccessBool = false;
            for(int i = 0; i < recipient.size(); i++){
                if(recipient.get(i).getSelect().isSelected()){
                    recipient.get(i).setCenter(centerChoice.getValue());
                    assignSuccessBool = true;
                    recipient.get(i).getSelect().setSelected(false);
                    selectAllCheckBox.setSelected(false);
                }
            }
            if(assignSuccessBool){
                util.save(recipient, center);
                util.load(recipient, center);
                Stage assignSuccess = new Stage();
                assignSuccess.setTitle("Success");      
                assignSuccess.setResizable(false);
                assignSuccess.initModality(Modality.APPLICATION_MODAL);
                assignSuccess.initOwner(stage);
                VBox assignSuccessVBox = new VBox(20);
                assignSuccessVBox.getChildren().add(new Text("Assigned Successfully!"));
                assignSuccessVBox.getChildren().add(okButton);
                assignSuccessVBox.setAlignment(Pos.CENTER);
                Scene assignSuccessScene = new Scene(assignSuccessVBox, 300, 200);
                assignSuccess.setScene(assignSuccessScene);
                assignSuccess.show();
                
                okButton.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent arg0) {
                        assignSuccess.close();
                    }
                });
            }else{
                Stage assignUnsuccess = new Stage();
                assignUnsuccess.setTitle("Unsuccess");      
                assignUnsuccess.setResizable(false);
                assignUnsuccess.initModality(Modality.APPLICATION_MODAL);
                assignUnsuccess.initOwner(stage);
                VBox assignUnsuccessVBox = new VBox(20);
                assignUnsuccessVBox.getChildren().add(new Text("No Recipient Is Assigned."));
                assignUnsuccessVBox.getChildren().add(okButton);
                assignUnsuccessVBox.setAlignment(Pos.CENTER);
                Scene assignUnsuccessScene = new Scene(assignUnsuccessVBox, 300, 200);
                assignUnsuccess.setScene(assignUnsuccessScene);
                assignUnsuccess.show();
                
                okButton.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent arg0) {
                        assignUnsuccess.close();
                    }
                });
            }
        }
    });

    backButton.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent arg0) {
            try {
                GridPane mohProfilePane = new GridPane();
                createScene(mohProfilePane);
                MOHProfile(stage, mohProfilePane, recipient, center);
                loadScene(stage, mohProfilePane);
            } catch (Exception e) {
                System.out.println("Error: " + e);
            }
        }
    });
}

这些是收件人的代码class


import javafx.scene.control.CheckBox;

/**
 * Recipient Class
 */
public class Recipient {
//__________________________________________________________________________________________________________________________________________________________________________________
//  Data Field
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
    private int id;
    private int age;
    private String name;
    private String phone;
    private String fDoseStatus;
    private String sDoseStatus;
    private String fDoseBatch;
    private String sDoseBatch;
    private String center;
    private LocalDate fDoseDate;
    private LocalDate sDoseDate;
    private CheckBox select;
//__________________________________________________________________________________________________________________________________________________________________________________
//  Constructor
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
    /**
     * Default Constructor
     */
    public Recipient(){}
    /**
     * Constructor specifying ID, Age, Name, Phone Number.
     * 
     * @param age
     * @param name
     * @param phone
     */
    public Recipient(int id, int age, String name, String phone){
        this.id = id;
        this.age = age;
        this.name = name;
        this.phone = phone;
        this.center = "N/A";
        this.fDoseStatus = "Pending";
        this.fDoseBatch = "N/A";
        this.sDoseStatus = "Pending";
        this.sDoseBatch = "N/A";
        this.fDoseDate = LocalDate.parse("0000-01-01");
        this.sDoseDate = LocalDate.parse("0000-01-01");
    }
//__________________________________________________________________________________________________________________________________________________________________________________
//  Mutator 
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
    /**
     * Set Recipient ID.
     * 
     * @param id
     */
    public void setId(int id){
        this.id = id;
    }
    /**
     * Set Recipient Age.
     * 
     * @param age
     */
    public void setAge(int age){
        this.age = age;
    }
    /**
     * Set Recipient Name.
     * 
     * @param name
     */
    public void setName(String name){
        this.name = name;
    }
    /**
     * Set Recipient Phone Number.
     * 
     * @param phone
     */
    public void setPhone(String phone){
        this.phone = phone;
    }
    /**
     * Set Recipient First Dose Status.
     * 
     * @param fDoseStatus
     */
    public void setFDoseStatus(String fDoseStatus){
        this.fDoseStatus = fDoseStatus;
    }
    /**
     * Set Recipient Second Dose Status.
     * 
     * @param sDoseStatus
     */
    public void setSDoseStatus(String sDoseStatus){
        this.sDoseStatus = sDoseStatus;
    }
    /**
     * Set Recipient First Dose Vaccine Batch Number
     * 
     * @param fDoseBatch
     */
    public void setFDoseBatch(String fDoseBatch){
        this.fDoseBatch = fDoseBatch;
    }
    /**
     * Set Recipient Second Dose Vaccine Batch Number
     * 
     * @param sDoseBatch
     */
    public void setSDoseBatch(String sDoseBatch){
        this.sDoseBatch = sDoseBatch;
    }
    /**
     * Set Recipient Assigned Center.
     * 
     * @param center
     */
    public void setCenter(String center){
        this.center = center;
    }
    /**
     * Set Recipient First Dose Appointment Date.
     * 
     * @param fDoseDate
     */
    public void setFDoseDate(LocalDate fDoseDate){
        this.fDoseDate = fDoseDate;
    }
    /**
     * Set Recipient Second Dose Appointment Date.
     * 
     * @param sDoseDate
     */
    public void setSDoseDate(LocalDate sDoseDate){
        this.sDoseDate = sDoseDate;
    }
    /**
     * Set CheckBox for Assigning.
     * 
     * @param select
     */
    public void setSelect(CheckBox select){
        this.select = select;
    }
//__________________________________________________________________________________________________________________________________________________________________________________
//  Accessor
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
    /**
     * Get Recipient ID.
     * 
     * @return id
     */
    public int getId(){
        return id;
    }
    /**
     * Get Recipient Age.
     * 
     * @return age
     */
    public int getAge(){
        return age;
    }
    /**
     * Get Recipient Name.
     * 
     * @return name
     */
    public String getName(){
        return name;
    }
    /**
     * Get Recipient Phone Number.
     * 
     * @return phone
     */
    public String getPhone(){
        return phone;
    }
    /**
     * Get Recipient First Dose Status.
     * 
     * @return fDoseStatus
     */
    public String getFDoseStatus(){
        return fDoseStatus;
    }
    /**
     * Get Recipient Second Dose Status.
     * 
     * @return sDoseStatus
     */
    public String getSDoseStatus(){
        return sDoseStatus;
    }
    /**
     * Get Recipient First Dose Vaccine Batch Number
     * 
     * @return fDoseBatch
     */
    public String getFDoseBatch(){
        return fDoseBatch;
    }
    /**
     * Get Recipient Second Dose Vaccine Batch Number
     * 
     * @return sDoseBatch
     */
    public String getSDoseBatch(){
        return sDoseBatch;
    }
    /**
     * Get Recipient Assigned Center.
     * 
     * @return center
     */
    public String getCenter(){
        return center;
    }
    /**
     * Get Recipient First Dose Appointment Date.
     * 
     * @return fDoseDate
     */
    public LocalDate getFDoseDate(){
        return fDoseDate;
    }
    /**
     * Get Recipient Second Dose Appointment Date.
     * 
     * @return sDoseDate
     */
    public LocalDate getSDoseDate(){
        return sDoseDate;
    }
    /**
     * Get CheckBox for Assigning.
     * 
     * @return select
     */
    public CheckBox getSelect(){
        return select;
    }
//__________________________________________________________________________________________________________________________________________________________________________________
//  Accessor
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
    /**
     * Initialise CheckBox
     */
    public void initialiseCheckBox(){
        this.select = new CheckBox();
    }
}

如果您想在对其余代码的干扰最小的情况下执行此操作,那么我建议将此逻辑放在自定义单元实现中。这是一个例子:

import java.time.LocalDate;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    var table = new TableView<Recipient>();
    table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    table.getItems().addAll(
        new Recipient("Recipient #1", LocalDate.of(0, 1, 1)),
        new Recipient("Recipient #2", LocalDate.of(2021, 4, 23)),
        new Recipient("Recipient #3", LocalDate.of(2020, 8, 30)),
        new Recipient("Recipient #4", LocalDate.of(0, 1, 1)),
        new Recipient("Recipient #5", LocalDate.of(2022, 1, 5))
    );

    var nameCol = new TableColumn<Recipient, String>("Name");
    nameCol.setCellValueFactory(data -> data.getValue().nameProperty());
    table.getColumns().add(nameCol);

    var doseCol = new TableColumn<Recipient, LocalDate>("First Dose");
    doseCol.setCellValueFactory(data -> data.getValue().firstDoseDateProperty());
    // Use custom cell implementation to display "N/A" for 0000-01-01
    doseCol.setCellFactory(tc -> new TableCell<>() {
      @Override protected void updateItem(LocalDate item, boolean empty) {
        super.updateItem(item, empty);
        if (empty || item == null) {
          setText(null);
        } else if (item.equals(LocalDate.of(0, 1, 1))) {
          // Might want to store 'LocalDate.of(0, 1, 1)' in a field to
          // avoid creating an object every time 'updateItem' is invoked
          setText("N/A");
        } else {
          setText(item.toString());
        }
      }
    });
    table.getColumns().add(doseCol);

    primaryStage.setScene(new Scene(table, 800, 600));
    primaryStage.show();
  }

  public static class Recipient {

    private final StringProperty name = new SimpleStringProperty(this, "name");
    public final void setName(String name) { this.name.set(name); }
    public final String getName() { return name.get(); }
    public final StringProperty nameProperty() { return name; }

    private final ObjectProperty<LocalDate> firstDoseDate = new SimpleObjectProperty<>(this, "firstDoseDate");
    public final void setFirstDoseDate(LocalDate firstDoseDate) { this.firstDoseDate.set(firstDoseDate); }
    public final LocalDate getFirstDoseDate() { return firstDoseDate.get(); }
    public final ObjectProperty<LocalDate> firstDoseDateProperty() { return firstDoseDate; }

    public Recipient() {}

    public Recipient(String name, LocalDate firstDoseDate) {
      setName(name);
      setFirstDoseDate(firstDoseDate);
    }
  }
}

如果您想对多列重复使用该实现,您可以将匿名 TableCell subclass 重构为命名 class。


我还建议您避免使用 PropertyValueFactory。 class 是在版本 8 中将 lambda 表达式添加到 Java 之前的一段时间内添加的。为了帮助开发人员避免在任何地方编写冗长的匿名 classes,他们添加了 class例如 PropertyValueFactory。然而,它有两个缺点:它依赖于反射,更重要的是,你失去了 compile-time 验证(例如,属性 是否确实存在于模型 class 中)。

您应该改用 lambda 表达式。您可以在上面的代码中看到这种方法的示例。当然,如果您的模型 class 公开 JavaFX 属性,则效果会更好。您的 Recipient 版本没有,但您可以更改 lambda 表达式以将 return 值包装在 属性.