【问题标题】:Howto select and edit TabelCell in TableView with mouseclick on a MenuItem of ContextMenu - JavaFX如何通过鼠标单击 ContextMenu 的 MenuItem 在 TableView 中选择和编辑 TabelCell - JavaFX
【发布时间】:2016-11-10 12:13:34
【问题描述】:

在单击鼠标或按下ContextMenu 的某个MenuItem 后,是否有可能在TableView 中选择和编辑TableCell?默认的TextFieldTableCell 实现仅支持在TableRow 具有焦点时按Enter 键或直接单击相应单元格以选择和编辑其内容。

【问题讨论】:

    标签: javafx tableview contextmenu menuitem tablecell


    【解决方案1】:

    如果正确理解您的问题,是的,您可以这样做。下面是一个示例,可让您使用上下文菜单编辑第二列中的单元格:

    import javafx.application.Application;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.control.ContextMenu;
    import javafx.scene.control.MenuItem;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableColumn.CellEditEvent;
    import javafx.scene.control.TableView;
    import javafx.scene.control.cell.TextFieldTableCell;
    import javafx.stage.Stage;
    
    public class EditableTableMCVE extends Application {
        @Override
        public void start(Stage stage) {
            int numOfCols = 10;
    
            ObservableList<ObservableList<String>> tableData = FXCollections.observableArrayList();
    
            // Generate dummy data.
            for (int i = 0; i < 100; i++) {
                ObservableList<String> row = FXCollections.observableArrayList();
    
                for (int j = 0; j < numOfCols; j++)
                    row.add("Row" + i + "Col" + j);
    
                tableData.add(row);
            }
    
            TableView<ObservableList<String>> table = new TableView<ObservableList<String>>();
            table.setEditable(true);
    
            // Add columns to the table.
            for (int i = 0; i < numOfCols; i++) {
                // We make all cells in column on index 1 editable.
                if (i == 1) {
                    table.getColumns().add(addEditableColumn(i, "Column " + i));
                } else {
                    table.getColumns().add(addColumn(i, "Column " + i));
                }
            }
    
            table.getItems().addAll(tableData);
    
            MenuItem editItem = new MenuItem("Edit");
            editItem.setOnAction(e -> {
                // We need to get the index of the selected row and the TableColumn
                // on the column index we want to edit.
                int selectedRowIndex = table.getSelectionModel().getSelectedIndex();
                table.edit(selectedRowIndex, table.getColumns().get(1));
            });
            ContextMenu menu = new ContextMenu(editItem);
            table.setContextMenu(menu);
    
            Scene scene = new Scene(table);
    
            stage.setScene(scene);
            stage.show();
        }
    
        /**
         * Returns a simple column.
         */
        private TableColumn<ObservableList<String>, String> addColumn(int index, String name) {
            TableColumn<ObservableList<String>, String> col = new TableColumn<ObservableList<String>, String>(name);
            col.setCellValueFactory(e -> new SimpleStringProperty(e.getValue().get(index)));
            return col;
        }
    
        /**
         * Returns an editable column.
         */
        private TableColumn<ObservableList<String>, String> addEditableColumn(int index, String name) {
            TableColumn<ObservableList<String>, String> col = new TableColumn<ObservableList<String>, String>(name);
            col.setCellValueFactory(e -> new SimpleStringProperty(e.getValue().get(index)));
    
            col.setCellFactory(TextFieldTableCell.forTableColumn());
            col.setOnEditCommit(new EventHandler<CellEditEvent<ObservableList<String>, String>>() {
                @Override
                public void handle(CellEditEvent<ObservableList<String>, String> t) {
                    ((ObservableList<String>) t.getTableView().getItems().get(t.getTablePosition().getRow())).set(index,
                            t.getNewValue());
                }
            });
            return col;
        }
    
        public static void main(String[] args) {
            launch();
        }
    }
    

    【讨论】:

    • 您好 Jonatan,是的,您完全理解我的问题。非常感谢您的解决方案!您与table.edit(selectedRowIndex, table.getColumns().get(1)); 的联系确实帮助我解决了我的问题。在此之前,我的代码是 tbl.getSelectionModel().select(currentRow, colCardTotal);,它仅在选择一行并按下 Enter 键以使 TableView 进入编辑模式时才有效。
    【解决方案2】:

    您可以通过扩展 TextFieldTableCell 来做到这一点。

    示例

    public class ContextTextFieldTableCell<S, T> extends TextFieldTableCell<S, T> {
    
        private void init() {
            MenuItem editItem = new MenuItem("edit");
            ContextMenu contextMenu = new ContextMenu(editItem);
            setContextMenu(contextMenu);
            setEditable(false);
            setOnContextMenuRequested(evt -> {
                editItem.setDisable(!(getTableColumn().isEditable() && getTableView().isEditable()));
            });
            editItem.setOnAction(evt -> {
                setEditable(true);
                getTableView().edit(getIndex(), getTableColumn());
            });
        }
    
        public ContextTextFieldTableCell() {
        }
    
        public ContextTextFieldTableCell(StringConverter<T> converter) {
            super(converter);
            init();
        }
    
        @Override
        public void cancelEdit() {
            super.cancelEdit();
            setEditable(false);
        }
    
        @Override
        public void commitEdit(T newValue) {
            super.commitEdit(newValue);
            setEditable(false);
        }
    
        public static <T> Callback<TableColumn<T, String>, TableCell<T, String>> cellFactory() {
            return cellFactory(new DefaultStringConverter());
        }
    
        public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> cellFactory(final StringConverter<T> converter) {
            if (converter == null) {
                throw new IllegalArgumentException();
            }
            return column -> new ContextTextFieldTableCell<>(converter);
        }
    
    }
    
    @Override
    public void start(Stage primaryStage) {
        TableView<Item<String>> tableView = createTable();
        tableView.setEditable(true);
    
        TableColumn<Item<String>, String> editColumn = new TableColumn("value(editable)");
        editColumn.setCellFactory(ContextTextFieldTableCell.cellFactory());
        editColumn.setCellValueFactory(cd -> cd.getValue().valueProperty());
        tableView.getColumns().add(editColumn);
    
        Scene scene = new Scene(tableView);
    
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    

    请注意,这删除了进入编辑模式的“标准”方式。如果您不需要此功能,您可以简单地使用cellFactory 自定义TextFieldTableCell:

    public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> cellFactory(final StringConverter<T> converter) {
        if (converter == null) {
            throw new IllegalArgumentException();
        }
        return column -> {
            final TextFieldTableCell<S, T> cell = new TextFieldTableCell<>(converter);
    
            MenuItem editItem = new MenuItem("edit");
            ContextMenu contextMenu = new ContextMenu(editItem);
            cell.setContextMenu(contextMenu);
    
            cell.setOnContextMenuRequested(evt -> {
                editItem.setDisable(!(cell.isEditable() && cell.getTableColumn().isEditable() && cell.getTableView().isEditable()));
            });
            editItem.setOnAction(evt -> {
                cell.getTableView().edit(cell.getIndex(), cell.getTableColumn());
            });
    
            return cell;
        };
    }
    

    【讨论】:

    • 感谢费边。您的解决方案在自定义 CellEditing 过程方面非常好!我将在下一个即将进行的项目中尝试这样做。
    猜你喜欢
    • 2014-02-07
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 2012-08-01
    相关资源
    最近更新 更多