【问题标题】:Problems implementing an editable TableView<ObservableList<String>实现可编辑 TableView<ObservableList<String> 的问题
【发布时间】:2016-01-25 19:01:40
【问题描述】:

所以我一直在尝试实现一个 TableView,您可以通过单击它来编辑列,然后按 Enter 键保存编辑。我从this 线程中的答案中获取了很多代码。结果如下:

import com.sun.javafx.collections.ObservableListWrapper;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.stage.Stage;

public class TestEditableTable extends Application {

    public void start(Stage stage) {

        TableView<ObservableList<String>> tableView = new TableView<ObservableList<String>>();
        tableView.setEditable(true);

        // Some dummy data.
        ObservableList<ObservableList<String>> dummyData = FXCollections.observableArrayList();
        ObservableList<String> firstRow = FXCollections.observableArrayList("Jack", "Smith");
        dummyData.add(firstRow);
        ObservableList<String> secondRow = FXCollections.observableArrayList("Peter", "Smith");
        dummyData.add(secondRow);

        TableColumn<ObservableList<String>, String> firstCol = new TableColumn<ObservableList<String>, String>(
                "First name");
        firstCol.setCellValueFactory(
                (TableColumn.CellDataFeatures<ObservableList<String>, String> param) -> new SimpleStringProperty(
                        param.getValue().get(0)));

        TableColumn<ObservableList<String>, String> secondCol = new TableColumn<ObservableList<String>, String>(
                "Last name");
        secondCol.setCellValueFactory(
                (TableColumn.CellDataFeatures<ObservableList<String>, String> param) -> new SimpleStringProperty(
                        param.getValue().get(1)));

        secondCol.setCellFactory(cell -> new EditableCell());

        tableView.getColumns().addAll(firstCol, secondCol);

        tableView.getItems().addAll(dummyData);

        Scene scene = new Scene(tableView);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

    class EditableCell extends TableCell<ObservableList<String>, String> {

        private TextField textfield = new TextField();

        // When the user presses the enter button the edit is saved.
        public EditableCell() {
            setOnKeyPressed(e -> {
                if (e.getCode().equals(KeyCode.ENTER)) {
                    commitEdit(textfield.getText());
                }
            });
        }

        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (isEmpty()) {
                setText(null);
                setGraphic(null);
            } else {
                if (isEditing()) {
                    textfield.setText(item);
                    setGraphic(textfield);
                    setText(null);
                } else {
                    setText(item);
                    setGraphic(null);
                }
            }
        }

        @Override
        public void startEdit() {
            super.startEdit();
            textfield.setText(getItem());
            setGraphic(textfield);
            setText(null);
        }

        @Override
        public void cancelEdit() {
            super.cancelEdit();
            setGraphic(null);
            setText(getItem());
        }

        @Override
        public void commitEdit(String value) {
            super.commitEdit(value);

            // This works. But gives me a "Discouraged access: The type 'ObservableListWrapper<String>' is not API (restriction on required library 'C:\Program Files\Java\jre1.8.0_60\lib\ext\jfxrt.jar')". 
            ObservableListWrapper<String> ob = ((ObservableListWrapper<String>) this.getTableRow().getItem());
            ob.set(1, value);

            // I had to put this in a Platform.runLater(), otherwise the textfield remained open.
            Platform.runLater(() -> {
                setText(value);
                setGraphic(null);
            });
        }
    }
}

这个程序运行正常。当您按下回车按钮时,单元格被编辑。但这有两个主要问题:

  1. 一旦我按下回车键并编辑了一个单元格。我无法通过单击它再次对其进行编辑。我需要按另一行才能再次编辑它。设置为专注于行的父级并没有解决问题。

  2. commitEdit() 中的代码有效。但它很难看,使用ObservableListWrapper 会给我警告“不鼓励访问:'ObservableListWrapper' 类型不是 API(对所需库的限制 'C:\Program Files\Java\jre1.8.0_60\lib\ext\jfxrt 。罐')”。此外,单元格索引是硬编码的,如果我在许多不同的列中使用它,它将无法工作。

上述问题均不可接受。

最终实现必须支持文本字段中的输入限制。据我了解,这意味着我需要访问单元格中显示的TextField 对象,就像我当前的实现一样。

【问题讨论】:

    标签: java javafx tableview tablecelleditor


    【解决方案1】:

    您正在将事件处理程序注册为 单元格 上的关键事件处理程序。在文本字段上注册一个处理程序更有意义,因为这是实际发生感兴趣事件的控件。另请注意,TextFields 在按下回车时触发动作事件。

    所以替换

        public EditableCell() {
            setOnKeyPressed(e -> {
                if (e.getCode().equals(KeyCode.ENTER)) {
                    commitEdit(textfield.getText());
                }
            });
        }
    

        public EditableCell() {
            textfield.setOnAction(e -> commitEdit(textfield.getText()));
        }
    

    这将确保正确维护编辑状态(您的事件处理程序不会发生这种情况,原因我不太清楚),因此它解决了“重新编辑”的问题。这也意味着您不必手动重置commitEdit 中的文本和图形。

    对于第二个问题,您可以直接转换为 ObservableList&lt;String&gt; 而不是 ObservableListWrapper&lt;String&gt;。但请注意,您也可以这样做

        @Override
        public void commitEdit(String value) {
            super.commitEdit(value);
            ObservableList<String> row = getTableView().getItems().get(getIndex());
            row.set(1, value);
        }
    

    这不仅避免了私有 API,而且完全避免了向下转换。

    【讨论】:

    • 这很有帮助。谢谢!我想我可以通过在 for 循环中动态创建列来修复硬编码的row.set(1, value)(将列名保存在列表中并为列名列表中的每个元素创建一个TableColumn)并将for循环整数传递给EditableCell 的构造函数,如果我有很多列。
    【解决方案2】:

    另一种方法是在 Buildpath 中用 JDK 库替换 JRE 库 项目->构建路径->配置构建路径 -1 删除 JRE 库

    -2 添加库 -2.1 -> 选择与您的 JDK 环境关联的 Java 库

    所有错误都会消失

    【讨论】:

      猜你喜欢
      • 2017-05-11
      • 2019-07-12
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多