格式化从 Oracle DB 检索的数据的 javaFX TableView 中的日期列



我按照这篇文章来适应日期格式,但得到了java.lang.NullPointerException。

控制器类:

这是我的代码: FXML 文件:

<AnchorPane id="AnchorPane" prefHeight="864.0" prefWidth="1090.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.60" fx:controller="idehmis.controller.PersonController">
<children>
<BorderPane layoutX="418.0" layoutY="159.0" prefHeight="705.0" prefWidth="1090.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="159.0">
<center>
<TableView fx:id="personTable" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<columns>
<TableColumn prefWidth="75.0" text="C1" />
<TableColumn prefWidth="75.0" text="C2" />
</columns>
</TableView>
</center>
</BorderPane>
<JFXTextField fx:id="Pmrn" layoutX="49.0" layoutY="43.0" maxWidth="117.0" minWidth="106.0" nodeOrientation="LEFT_TO_RIGHT" prefColumnCount="8" prefHeight="31.0" prefWidth="117.0" promptText="MRN" unFocusColor="#0f098a">
</JFXTextField>
<JFXTextField fx:id="Plastname" layoutX="47.0" layoutY="88.0" maxWidth="121.0" minWidth="106.0" nodeOrientation="LEFT_TO_RIGHT" prefColumnCount="8" prefHeight="31.0" prefWidth="117.0" promptText="Last Name" unFocusColor="#190879">
</JFXTextField>
<JFXDatePicker fx:id="Pdateofbirth" layoutX="210.0" layoutY="43.0" prefHeight="31.0" prefWidth="201.0" promptText="Date Of Birth" />
<Button fx:id="getAllData" layoutX="573.0" layoutY="30.0" mnemonicParsing="false" onAction="#SubmitButton" text="Retrieve data" />
</children>
</AnchorPane>

下面是人员类:

public class Person {
public final StringProperty mrn;
public final StringProperty lastname;
//public final StringProperty dateofbirth;
public ObjectProperty<LocalDate> dateofbirth = new SimpleObjectProperty<>();
public Person() {
this.mrn = new SimpleStringProperty();
this.lastname = new SimpleStringProperty();
//this.dateofbirth = new SimpleStringProperty();
this.dateofbirth = new SimpleObjectProperty<>();
}
public String getMRN() {
return mrn.get();
}
public void setMRN(String mrn) {
this.mrn.set(mrn);
}
public StringProperty mrnProperty() {
return mrn;
}
public String getLarstName() {
return lastname.get();
}
public void setLastName(String lastName) {
this.lastname.set(lastName);
}
public StringProperty lastNameProperty() {
return lastname;
}
public Object getDateOfBirth() {
return dateofbirth.get();
}
public void setDateOfBirth(LocalDate dateofbirth) {
this.dateofbirth.set(dateofbirth);
}
public ObjectProperty<LocalDate> dateOfBirthProperty() {
return dateofbirth;
}
}

这是控制器:

public class PersonController implements Initializable {
@FXML
private TableView<Person> personTable;
@FXML
private JFXTextField Pmrn;
@FXML
private JFXTextField Plastname;
@FXML
private JFXDatePicker Pdateofbirth;
@FXML
private ObservableList<Person> data;
@FXML
private Button getAllData;
@FXML
TableColumn<Person, String> MRN;
@FXML
TableColumn<Person, String> LASTNAME;
@FXML
TableColumn<Person, LocalDate> DATEOFBIRTH;
SimpleDateFormat sdf = new SimpleDateFormat("dd,MMM,yyyy", Locale.getDefault());
@Override
public void initialize(URL url, ResourceBundle rb) {
DATEOFBIRTH.setCellValueFactory(new PropertyValueFactory<>("dateOfBirth"));
DATEOFBIRTH.setCellFactory(new PersonController.ColumnFormatter<>(DateTimeFormatter.ofPattern("MM/dd/yyyy")));
}
@FXML
void SubmitButton(ActionEvent event) {
if (event.getSource() == getAllData) {
try {
populatetData();
} catch (Exception ex) {
out.println(ex);
}
}
}
private class ColumnFormatter<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
private final DateTimeFormatter format;
public ColumnFormatter(DateTimeFormatter format) {
super();
this.format = format;
}
@Override
public TableCell<S, T> call(TableColumn<S, T> arg0) {
return new TableCell<S, T>() {
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
LocalDate ld = (LocalDate) item;
String val = ld.format(format);
setGraphic(new Label(val));
}
}
};
}
}
@SuppressWarnings("Convert2Lambda")
public void populatetData() throws Exception {
Connection conn = null;
Person pt = new Person();
conn = DBConnection.getConnection();
String SQL;
Person p = new Person();
try {
conn = DBConnection.getConnection();
data = FXCollections.observableArrayList();
SQL = "SELECT MRN, LASTNAME, DATEOFBIRTH FROM " + "HIVP.PATIENT";
out.println(SQL);
ResultSet rs = conn.createStatement().executeQuery(SQL);
if (rs != null) {
while (rs.next()) {
p.setMRN(rs.getString(1));
p.setLastName(rs.getString(2));
Date x = rs.getDate(3);
if (x != null) {
p.setDateOfBirth(rs.getDate(3).toLocalDate());
} else {
p.setDateOfBirth(LocalDate.MIN);
}
data.addAll(p);
}
Platform.runLater(new Runnable() {
@Override
public void run() {
personTable.setItems(data);
}
});
}
} catch (Exception e) {
out.println("ERROR GETTING DATA: " + e);
} finally {
if (conn != null) {
DBConnection.closeConnection((OracleConnection) conn);
}
}
}
}

Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: 
file:/C:/Users/abayazids15/Documents/NetBeansProjects/IDEHMIS/dist/run1719879236/IDEHMIS.jar!/idehmis/view/Person.fxml
file:/C:/Users/abayazids15/Documents/NetBeansProjects/IDEHMIS/dist/run1719879236/IDEHMIS.jar!/idehmis/view/mainApplication.fxml:66
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.access$2700(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$IncludeElement.constructValue(FXMLLoader.java:1143)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:746)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
at idehmis.IDEHMIS.start(IDEHMIS.java:21)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
... 1 more
Caused by: java.lang.NullPointerException
at idehmis.controller.PersonController.initialize(PersonController.java:58)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
... 23 more
Exception running application idehmis.IDEHMIS
Java Result: 1

我做错了什么来获得NullPointException。 请帮忙。谢谢

您只是忘记在列中输入 ID...它必须是这样的:

<TableColumn fx:id="MRN" prefWidth="75.0" text="C1" />
<TableColumn fx:id="LASTNAME" prefWidth="75.0" text="C2" />

如果没有它们,"初始化"方法中的MRN字段将保持"null",因为FXMLLoader在fxml文件中找不到匹配的(按ID)字段。 在我看来,虽然有两个字段的名称仅大小写不同(例如,在您的代码中,TextField "mrn" 和 TableColumn "MRN") 实际上有效,但这非常令人困惑。

此外,您的数据模型和填充数据的方法存在问题:

  • 首先,您的 TableView 应该是 Person 类型,而不是 List:Person 是您的 Table 将保存的数据类型。因此,应将表列声明为表列
  • 其次,你必须决定是要使用FXML还是使用Java代码。表中已经有列(通过 FXML),但在 populateData 方法中,您清除它们并尝试再次添加它们。如果您事先知道列,那么只需使用 FXML 并删除填充数据的这一部分
  • 第三,当您读取从数据库中获得的结果时,您应该为每一行创建一个 Person 对象,然后将该对象添加到数据列表中。像这样:

    while (rs.next()) {                   
    Person p = new Person();
    p.setMRN(rs.getString(1));
    p.setLastName(rs.getString(2));
    Date x = rs.getDate(3);
    if (x != null) {
    p.setDateOfBirth(rs.getDate(3).toLocalDate());
    } else {
    p.setDateOfBirth(LocalDate.MIN);
    }
    data.add(p);
    } 
    

尝试使用调试器跟踪代码,它将帮助您理解。

至于日期格式,我建议使用日期时间格式化程序:

DATEOFBIRTH.setCellValueFactory(new PropertyValueFactory<>("dateOfBirth"));
DATEOFBIRTH.setCellFactory(new PersonController.ColumnFormatter<>(DateTimeFormatter.ofPattern("MM/dd/yyyy")));

并通过以下方式修改列格式化程序:

private class ColumnFormatter<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
private final DateTimeFormatter format;
public ColumnFormatter(DateTimeFormatter format) {
super();
this.format = format;
}
@Override
public TableCell<S, T> call(TableColumn<S, T> arg0) {
return new TableCell<S, T>() {
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
LocalDate ld = (LocalDate) item;
String val = ld.format(format);
setGraphic(new Label(val));
}
}
};
}
}

最新更新