我正在开发一个带有 TableView 的 JavaFX 应用程序,用于管理员工记录。我有一个 EmployeeRepository 类用于处理 CRUD 操作,它与“CsvHandler”类通信以将数据保存在 csv 中,还有一个 EmployeeManagementController 用于与 TableView 交互。
我面临的问题是,当我通过 EmployeeDetailsController 启动的对话框添加或更新员工记录时,EmployeeManagementController 中的 TableView 不会更新以反映这些更改。
以下是相关代码的简要概述:
EmployeeRepository:管理 CRUD 操作并维护 TableView 应绑定到的 ObservableList
EmployeeManagementController:用employeeObservableList初始化TableView,当添加或更新记录时,它应该被更新。
EmployeeDetailsController:处理添加或更新记录的对话框,并调用 EmployeeRepository 中的方法来保存数据。
尽管在操作后更新了 EmployeeRepository 中的 ObservableList,但 EmployeeManagementController 中的 TableView 并未反映这些更改。
这是 EmployeeRepository 类:
public class EmployeeRepository {
private final CsvHandler csvHandler;
private final String EMPLOYEE_DATA_FILE = "Data/employeeData.csv";
private final List<String[]> employeeData;
private final ObservableList<Employee> employeeList;
private final String[] HEADERS;
public EmployeeRepository() {
csvHandler = new CsvHandler(EMPLOYEE_DATA_FILE);
employeeData = csvHandler.retrieveCsvData(true);
employeeList = FXCollections.observableArrayList(getAllEmployees());
HEADERS = csvHandler.retrieveFieldNames();
}
public Employee convertArrayToEmployee(String[] employeeData) {
return new Employee(
Integer.parseInt(employeeData[0]),
employeeData[1],
employeeData[2],
employeeData[3],
employeeData[4],
employeeData[5],
employeeData[6],
employeeData[7],
employeeData[8],
employeeData[9],
employeeData[10],
employeeData[11],
employeeData[12],
employeeData[13],
employeeData[14],
Double.parseDouble(employeeData[15]),
Double.parseDouble(employeeData[16]),
Double.parseDouble(employeeData[17]),
Double.parseDouble(employeeData[18]),
Double.parseDouble(employeeData[19]),
Double.parseDouble(employeeData[20])
);
}
public List<Employee> getAllEmployees() {
List<Employee> employees = new ArrayList<>();
for (String[] row : employeeData) {
employees.add(convertArrayToEmployee(row));
}
return employees;
}
public ObservableList<Employee> getEmployeeList() {
return employeeList;
}
public boolean recordExists(String[] record, int currentEmpId) {
for (String[] row : employeeData) {
if (Integer.parseInt(row[0]) != currentEmpId && // EmployeeID
(record[4].equals(row[4]) || // address
record[5].equals(row[5]) || // phone number
record[7].equals(row[7]) || // SSS
record[8].equals(row[8]) || // PhilHealth
record[9].equals(row[9]) || // TIN
record[10].equals(row[10]))) { // Pag-IBIG
return true;
}
}
return false;
}
public void addEmployeeRecord(String[] record) {
if (recordExists(record, -1)) {
AlertUtil.showDuplicateRecordExists();
return;
}
employeeData.add(record);
employeeList.add(convertArrayToEmployee(record));
csvHandler.writeDataToCsv(employeeData, HEADERS);
employeeList.clear();
employeeList.addAll(getAllEmployees());
AlertUtil.showRecordSavedAlert();
System.out.println("Record saved");
}
public int getNewEmployeeID() {
return Integer.parseInt(employeeData.getLast()[0]) + 1;
}
public void updateEmployeeRecord(String[] record) {
if (recordExists(record, Integer.parseInt(record[0]))) {
AlertUtil.showDuplicateRecordExists();
return;
}
for (int i = 0; i < employeeData.size(); i++) {
String[] row = employeeData.get(i);
if (row[0].equals(record[0])) {
employeeData.set(i, record);
employeeList.set(i, convertArrayToEmployee(record));
break;
}
}
csvHandler.writeDataToCsv(employeeData, HEADERS);
employeeList.clear();
employeeList.addAll(getAllEmployees());
AlertUtil.showRecordUpdatedAlert();
System.out.println("Record Updated");
}
public void deleteEmployeeRecord(int employeeId) {
employeeData.removeIf(row -> row[0].equals(String.valueOf(employeeId)));
csvHandler.writeDataToCsv(employeeData, HEADERS);
employeeList.clear();
employeeList.addAll(getAllEmployees());
AlertUtil.showRecordDeletedAlert();
System.out.println("Record deleted");
}
}
这是 EmployeeManagementController:
public class EmployeeManagementController {
private final EmployeeRepository empDataService;
private final ObservableList<Employee> employeeObservableList;
@FXML
private TableView<Employee> employeeTable;
@FXML
private TableColumn<Employee, Integer> employeeIdColumn;
@FXML
private TableColumn<Employee, String> firstNameColumn, lastNameColumn, tinNoColumn, sssNoColumn, philhealthNoColumn, pagibigNoColumn;
public EmployeeManagementController() {
empDataService = new EmployeeRepository();
employeeObservableList = empDataService.getEmployeeList();
}
@FXML
public void initialize() {
initializeTableColumns();
loadEmployeeData();
handleViewEmployeeDetails();
}
@FXML
private void handleAddNewRecord() {
new EmployeeDetailsController().displayEmployeeDialog(false, null, false);
}
@FXML
private void handleUpdateRecord() { Employee selectedEmployee = selectedEmployee();
if (selectedEmployee != null) {
new EmployeeDetailsController().displayEmployeeDialog(true, selectedEmployee, false);
} else {
AlertUtil.showNoSelectionAlert("Please select an employee record to update");
}
}
@FXML
public void handleDeleteRecord() {
Employee selectedEmployee = selectedEmployee();
if (selectedEmployee == null) {
AlertUtil.showNoSelectionAlert("Please select an employee record to delete");
return;
}
boolean confirmed = AlertUtil.showConfirmationAlert("Confirm Deletion", "Are you sure you want to delete this employee record? This action cannot be undone.");
if (confirmed) {
empDataService.deleteEmployeeRecord(selectedEmployee.getEmployeeID());
}
}
private void handleViewEmployeeDetails() {
employeeTable.setOnMouseClicked((MouseEvent event) -> {
if (event.getClickCount() == 2) {
new EmployeeDetailsController().displayEmployeeDialog(false, selectedEmployee(), true);
}
});
}
private void initializeTableColumns() {
employeeIdColumn.setCellValueFactory(new PropertyValueFactory<>("employeeID"));
firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
lastNameColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));
tinNoColumn.setCellValueFactory(new PropertyValueFactory<>("tinNumber"));
sssNoColumn.setCellValueFactory(new PropertyValueFactory<>("sssNumber"));
philhealthNoColumn.setCellValueFactory(new PropertyValueFactory<>("philhealthNumber"));
pagibigNoColumn.setCellValueFactory(new PropertyValueFactory<>("pagibigNumber"));
bindTableColumnsToTableViewWidth();
}
private void loadEmployeeData() {
employeeTable.setItems(employeeObservableList);
}
private Employee selectedEmployee() {
return employeeTable.getSelectionModel().getSelectedItem();
}
}
这是 EmployeeDetailsController:
public class EmployeeDetailsController {
private final EmployeeRepository empRepository = new EmployeeRepository();
private Employee employee;
private boolean updateMode = false;
public void setEmployee(Employee employee) {
this.employee = employee;
updateMode = true;
populateFields();
}
@FXML
public void handleSaveRecord() {
if (!validateFields()) {
AlertUtil.showIncompleteDataAlert();
return;
}
try {
if (AlertUtil.confirmDetails()) {
String[] record = retrieveInputAsStringArray();
if (updateMode) {
handleUpdateMode(record);
} else {
handleAddMode(record);
}
}
} catch (NumberFormatException e) {
AlertUtil.showAlert(Alert.AlertType.ERROR, "Invalid Number Format", "Please enter a valid number.");
}
}
private void handleAddMode(String[] record) {
empRepository.addEmployeeRecord(record);
}
private void handleUpdateMode(String[] record) {
empRepository.updateEmployeeRecord(record);
}
public void displayEmployeeDialog(boolean updateMode, Employee employee, boolean showOnly) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/View/EmployeeDetails.fxml"));
DialogPane empDetailsDialogPane = loader.load();
EmployeeDetailsController controller = loader.getController();
if (updateMode) {
controller.setEmployee(employee);
} else if (employee != null) {
controller.setEmployee(employee);
controller.disableTextFields();
}
Dialog<ButtonType> dialog = new Dialog<>();
dialog.setDialogPane(empDetailsDialogPane);
if (showOnly) {
empDetailsDialogPane.lookupButton(ButtonType.OK).setVisible(false);
empDetailsDialogPane.lookupButton(ButtonType.CANCEL).setVisible(false);
}
Optional<ButtonType> clickedButton = dialog.showAndWait();
if (clickedButton.isPresent() && clickedButton.get() == ButtonType.OK && !showOnly) {
controller.handleSaveRecord();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void disableTextFields() {
for (TextField textField : textFields) {
textField.setEditable(false);
}
}
}
您可以显式地尝试刷新表视图以反映可观察列表的底层更改。
/**
* Refresh the table contents when the underlying observable list tracked by
* table gets updated
*/
public void refresh() {
employeeTable.getColumns().get(0).setVisible(false);
employeeTable.getColumns().get(0).setVisible(true);
}