仍然无法理解为什么我的表视图更改侦听器不起作用



我知道我的问题很琐碎,解决方案表面上是,但我仍然无法处理它,所以需要帮助。问题是我的代码中的 TableView ListChangeListener 不显示更新的更改。在提出问题之前,我已经阅读了许多主题,手册和示例

Javafx:检测对表视图所做的所有更改,包括表行的添加/删除以及对任何表行的单元格编辑

Java ListChangeListener WasUpdate(( 不起作用

https://docs.oracle.com/javase/8/javafx/api/javafx/collections/ListChangeListener.Change.html#wasUpdated--

http://java-buddy.blogspot.com/2014/11/example-of-listchangelistener-for.html

但仍然无法理解为什么我的代码不起作用。我已经添加了extractor但它对我没有帮助。

这是我代码的一部分

public class mainTableOverviewController {

@FXML
private TableView<EmailData> emailTableView;
@FXML
private TableColumn<EmailData, String> emailNameColumn;
@FXML
private TableColumn<EmailData, String> emailLoginColumn;
@FXML
private TableColumn<EmailData, String> emailPasswordColumn;
@FXML
private TableColumn<EmailData, String> emailCommentsColumn;
@FXML
private Button handleDeletePerson;

private MainApp mainApp;
public mainTableOverviewController() {
}
@FXML
private void initialize() {
emailTableView.setEditable(true);
emailTableView.getSelectionModel().setCellSelectionEnabled(true);
emailTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
Callback<TableColumn<EmailData, String>, TableCell<EmailData, String>> cellFactory =
new Callback<TableColumn<EmailData, String>, TableCell<EmailData, String>>() {
public TableCell call(TableColumn p) {
return new EditingCell();
}
};
emailNameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
emailNameColumn.setCellFactory(cellFactory);
emailNameColumn.setOnEditCommit(
t -> t.getTableView().getItems().get(
t.getTablePosition().getRow()).setName(t.getNewValue())
);
emailLoginColumn.setCellValueFactory(cellData -> cellData.getValue().loginProperty());
emailLoginColumn.setCellFactory(cellFactory);
emailLoginColumn.setOnEditCommit(
t -> t.getTableView().getItems().get(
t.getTablePosition().getRow()).setLogin(t.getNewValue())
);
emailPasswordColumn.setCellValueFactory(cellData -> cellData.getValue().passwordProperty());
emailPasswordColumn.setCellFactory(cellFactory);
emailPasswordColumn.setOnEditCommit(
t -> t.getTableView().getItems().get(
t.getTablePosition().getRow()).setPassword(t.getNewValue())
);
emailCommentsColumn.setPrefWidth(120);
emailCommentsColumn.setCellValueFactory(cellData -> cellData.getValue().commentsProperty());
emailCommentsColumn.setCellFactory(cellFactory);
emailCommentsColumn.setOnEditCommit(
t -> t.getTableView().getItems().get(
t.getTablePosition().getRow()).setComments(t.getNewValue())
);
emailData.addListener((Change<? extends EmailData> c) -> {
while (c.next()) {
if (c.wasAdded()) {
System.out.println("Added:");
c.getAddedSubList().forEach(System.out::println);
System.out.println();
}
if (c.wasRemoved()) {
System.out.println("Removed:");
c.getRemoved().forEach(System.out::println);
System.out.println();
}
if (c.wasUpdated()) {
System.out.println("Updated:");
emailData.subList(c.getFrom(), c.getTo()).forEach(System.out::println);
System.out.println();
}
}
});
emailTableView.getColumns().setAll(emailNameColumn, emailLoginColumn, emailPasswordColumn, emailCommentsColumn, actionCol);
}
}
@FXML
private void handleDeletePerson() {
int selectedIndex = emailTableView.getSelectionModel().getSelectedIndex();
if (selectedIndex >= 0) {
deletedDataList.add(emailTableView.getItems().get(selectedIndex));
emailTableView.getItems().remove(selectedIndex);
menuItemDisable.set(false);
} else {
nothingSelected();
}
}
class EditingCell extends TableCell<EmailData, String> {
TextField textField;
EditingCell() {
}
@Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
if (textField == null) {
createTextField();
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
Platform.runLater(new Runnable() {
@Override
public void run() {
textField.requestFocus();
textField.selectAll();
}
});
}
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}

@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
emailTableView.getColumns().get(0).setVisible(false);
emailTableView.getColumns().get(0).setVisible(true);
setText(getString());
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()
* 2);
textField.focusedProperty().addListener(
new ChangeListener<Boolean>() {
@Override
public void changed(
ObservableValue<? extends Boolean> arg0,
Boolean arg1, Boolean arg2) {
if (!arg2) {
commitEdit(textField.getText());
}
}
});
textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(textField.getText());
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
} else if (t.getCode() == KeyCode.TAB) {
commitEdit(textField.getText());
TableColumn nextColumn = getNextColumn(!t.isShiftDown());
if (nextColumn != null) {
getTableView().edit(getTableRow().getIndex(),
nextColumn);
}
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem();
}
private TableColumn<EmailData, ?> getNextColumn(boolean forward) {
List<TableColumn<EmailData, ?>> columns = new ArrayList<>();
for (TableColumn<EmailData, ?> column : getTableView().getColumns()) {
columns.addAll(getLeaves(column));
}
// There is no other column that supports editing.
if (columns.size() < 2) {
return null;
}
int nextIndex = columns.indexOf(getTableColumn());
if (forward) {
nextIndex++;
if (nextIndex > columns.size() - 1) {
nextIndex = 0;
}
} else {
nextIndex--;
if (nextIndex < 0) {
nextIndex = columns.size() - 1;
}
}
return columns.get(nextIndex);
}
private List<TableColumn<EmailData, ?>> getLeaves(
TableColumn<EmailData, ?> root) {
List<TableColumn<EmailData, ?>> columns = new ArrayList<>();
if (root.getColumns().isEmpty()) {
if (root.isEditable()) {
columns.add(root);
}
return columns;
} else {
for (TableColumn<EmailData, ?> column : root.getColumns()) {
columns.addAll(getLeaves(column));
}
return columns;
}
}
}
}

以及列表声明所在的类:

public class MainApp extends Application {
public static ObservableList<EmailData> backupList = FXCollections.observableArrayList();
public static ObservableList<EmailData> emailData = FXCollections.observableArrayList(ed ->
new Observable[]{
ed.nameProperty(),
ed.loginProperty(),
ed.passwordProperty(),
ed.commentsProperty()
});
private BorderPane rootLayout;
public MainApp() {
}
public static void readCryptedData(String s) {
try {
switch (s) {
case "initData":
emailData = readDataFromStream(decryptFileBytes(libraryPath, salt, nonce));
break;
default:
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
launch(args);
}
public static ObservableList<EmailData> getEmailData() {
return emailData;
}

@Override
public void start(Stage primaryStage) {
MainApp.primaryStage = primaryStage;
MainApp.primaryStage.setResizable(false);
MainApp.primaryStage.getIcons().add(new Image(imageFile.toURI().toString()));
initRootLayout();
try {
showFirstView();
} catch (IOException e) {
e.printStackTrace();
}
}
private void initRootLayout() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("/fxml/RootLayout.fxml"));
rootLayout = loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
menuItemDisable.set(true);
} catch (IOException e) {
e.printStackTrace();
}
}

public Stage getPrimaryStage() {
return primaryStage;
}

@Override
public void stop() {
if (emailData.size() != 0) {
saveDataToFile();
}
}
}

我将非常感谢任何帮助。

在查找了我的问题的评论和缺点后,我发现我需要自己在代码中搜索问题。希望有人会发现这个问题和答案有用。 问题出在我的读取方法readDataFromStream().在阅读上面提到的主题之前,我使用了这种声明ObservableList

public static ObservableList<EmailData> emailData = FXCollections.observableArrayList(); 

我的readDataFromStream看起来像:

public static ObservableList<EmailData> readDataFromStream(byte[] bytes) {
ObservableList<EmailData> emailData = FXCollections.observableArrayList();
try {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
List<EmailData> list = (List<EmailData>) ois.readObject();
emailData = FXCollections.observableList(list);
bis.close();
ois.close();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
return emailData;
}

然后我读到我需要使用提取器创建列表。我ObservableList声明更改为:

ObservableList<EmailData> emailData = FXCollections.observableArrayList(ed ->
new Observable[]{
ed.nameProperty(),
ed.loginProperty(),
ed.passwordProperty(),
ed.commentsProperty()
});

但我的readDataFromStream()方法保持不变。现在我把它改成:

public static ObservableList<EmailData> readDataFromStream(byte[] bytes) {
ObservableList<EmailData> emailData = FXCollections.observableArrayList(ed ->
new Observable[]{
ed.nameProperty(),
ed.loginProperty(),
ed.passwordProperty(),
ed.commentsProperty()
});
try {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
List<EmailData> list = (List<EmailData>) ois.readObject();
emailData = FXCollections.observableList(
list,
(EmailData tp) -> new Observable[]{tp.nameProperty(), tp.passwordProperty(),
tp.loginProperty(), tp.commentsProperty()});
bis.close();
ois.close();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
return emailData;
}

wasUpdated()ListChangeListener.Change方法现在就像一个魅力。

希望它能帮助像我这样的新手。

最新更新