如何在 ListView 中显示对象的文本字段中的更改?

问题描述 投票:0回答:2

我目前正在用 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 很陌生,这是我完成课程的第一个项目。 :)

谢谢你的帮助,你太善良了。

赫茨尔·伊奇

java sqlite listview java-stream changelistener
2个回答
1
投票

不完全确定我是否理解这个问题,但我猜测你可以通过分别向 headerZettel 和 textZettel 添加专用侦听器来实现你想要的。然后看来,既然你不断地听标题和文本,你就可以摆脱

updateZettelInDatabase()
类似的东西

headerZettel.textProperty().addListener((observable, oldValue, newValue) -> ...etc

...但我也是 Java 新手,所以请小心我的建议


0
投票

所以我尝试了一切,从重构类以使用 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());
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.