我目前正在用 Java 编写一个小型 Zettelkasten-app* 并在 scenebuilder 中构建大部分 GUI。
与问题无关的进一步描述,仅在感兴趣时阅读斜体部分: (该应用程序使您可以记下保存在 SQLite3 表中的笔记,并在此过程中定义流行语,然后搜索您的其他笔记,并向您提供包含相同流行语的 Zettel 列表。您还可以将 Zettel 分组到集合中)
我有一个 ListView,它允许您选择其中一个 Zettel,并且其标题和文本被加载到 TextFields 中进行编辑。我希望 ListView 在打字过程中实时显示 Zettel 中的更改(数据库中的文本会随着每次击键而更新)。
使用我当前的解决方案,LV 中 Zettel 的 Thumb 或 Cell 仅在我单击另一个时更新。
这是我负责该功能的代码。
控制器类:
//variables
@FXML
public TextField headerZettel;
@FXML
public TextArea textZettel;
@FXML
private ListView<Zettel> zettelList;
private ObservableList<Zettel> zettelData = FXCollections.observableArrayList();
public void initializeZettelList() {
// get ZettelData from database and add to list
zettelList.setItems(zettelData);
//CellFactory for manipulation of the listcells
zettelList.setCellFactory(param -> new ListCell<>() {
private final VBox vbRoot = new VBox();
private final Label lblHeader = new Label();
private final Label lblText = new Label();
private Zettel zettel;
{
lblHeader.setStyle("-fx-font-weight: bold;");
vbRoot.setSpacing(10);
vbRoot.getChildren().addAll(lblHeader, lblText);
}
@Override
protected void updateItem(Zettel z, boolean empty) {
super.updateItem(z, empty);
if (z != null && !empty) {
lblHeader.setText(z.getHeader());
lblText.setText(z.getText().split("\n")[0]);
setGraphic(vbRoot);
zettel = z; // Save the reference to the associated Zettel object
} else {
setGraphic(null);
zettel = null; // Clear the reference when the cell is empty
}
}
});
// ChangeListener to load and handle Zettel-Objects
zettelList.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Zettel>() {
@Override
public void changed(ObservableValue<? extends Zettel> observable, Zettel oldValue, Zettel newValue) {
if (newValue != null) {
currentZettelId = newValue.getZettelId();
headerZettel.setText(newValue.getHeader());
textZettel.setText(newValue.getText());
} else {
currentZettelId = null;
headerZettel.clear();
textZettel.clear();
}
}
});
}
这里是带有 ZettelData 的流:
public void updateZettelInDatabase() {
String header = getHeaderZettelText();
String text = getTextZettelText();
if (currentZettelId != null) {
Zettel zettelToUpdate = zettelData.stream()
.filter(z -> Arrays.equals(z.getZettelId(), currentZettelId))
.findFirst()
.orElse(null);
if (zettelToUpdate != null) {
zettelToUpdate.setHeader(header);
zettelToUpdate.setText(text);
//Update Zettel-Object in database
ZettelUpdater zettelUpdater = new ZettelUpdater();
zettelUpdater.updateZettel(header, text, currentZettelId);
} else {
System.out.println("Keine aktuelle ZettelId vorhanden.");
}
}
}
来自数据库类:
public static ObservableList<Zettel> getZettelData(){
ObservableList<Zettel> zettelData = FXCollections.observableArrayList();
try (Connection conn = DriverManager.getConnection(connectionString);
PreparedStatement stmt = conn.prepareStatement("SELECT ZettelId, Header, Text, Date FROM zettel");
ResultSet rs = stmt.executeQuery()) {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
while (rs.next()) {
byte[] zettelId = rs.getBytes("ZettelId");
String header = rs.getString("Header");
String text = rs.getString("Text");
String dateString = rs.getString("Date");
LocalDate date = LocalDate.parse(dateString, dateFormatter);
Zettel zettel = new Zettel();
zettel.setZettelId(zettelId);
zettel.setHeader(header);
zettel.setText(text);
zettel.setDate(date);
zettelData.add(zettel);
}
} catch (SQLException e) {
e.printStackTrace();
}
return zettelData;
}
有任何提示或想法,如何使其正常运行吗?
总的来说,我也很高兴接受各种批评,因为我对 java 很陌生,这是我完成课程的第一个项目。 :)
谢谢你的帮助,你太善良了。
赫茨尔·伊奇
不完全确定我是否理解这个问题,但我猜测你可以通过分别向 headerZettel 和 textZettel 添加专用侦听器来实现你想要的。然后看来,既然你不断地听标题和文本,你就可以摆脱
updateZettelInDatabase()
类似的东西
headerZettel.textProperty().addListener((observable, oldValue, newValue) -> ...etc
...但我也是 Java 新手,所以请小心我的建议
所以我尝试了一切,从重构类以使用 StringProperties 而不是字符串,实现其他更新逻辑,以及将 ListView 和 zettelData 绑定在一起并且不覆盖任何地方的绑定。什么都没起作用。 最终有帮助的是这行代码:
Platform.runLater(() -> zettelList.refresh());
此方法可保存对按键进行的编辑
@FXML
void saveOnChangeZettel(KeyEvent event){
if (currentZettelId != null) { // Überprüfe, ob eine aktuelle ZettelId vorhanden ist
updateZettelInDatabase();
checkForBuzzwordsInCurrentZettel(currentZettelId);
Platform.runLater(() -> zettelList.refresh());
}
}