如何使用鼠标在ContextMenu-JavaFX的菜单项上单击来选择和编辑TableView中的TabelCell

如何使用鼠标在ContextMenu-JavaFX的菜单项上单击来选择和编辑TableView中的TabelCell,javafx,tableview,contextmenu,menuitem,tablecell,Javafx,Tableview,Contextmenu,Menuitem,Tablecell,在鼠标单击或按键按下上下文菜单的某个菜单项后,是否有可能在表格视图中选择和编辑表格单元格?默认的TextFieldTableCell实现仅支持在TableRow具有焦点时按Enter键,或直接单击相应单元格以选择和编辑其内容。您可以通过扩展TextFieldTableCell来完成此操作 示例 public class ContextTextFieldTableCell<S, T> extends TextFieldTableCell<S, T> { priva

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

您可以通过扩展
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);
    }

}

如果正确理解您的问题,是的,您可以这样做。以下示例允许您使用关联菜单编辑第二列中的单元格:

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();
    }
}
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.ContextMenu;
导入javafx.scene.control.MenuItem;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TableColumn.CellEditEvent;
导入javafx.scene.control.TableView;
导入javafx.scene.control.cell.TextFieldTableCell;
导入javafx.stage.stage;
公共类EditableTableTableMCVE扩展了应用程序{
@凌驾
公众假期开始(阶段){
int numocols=10;
ObservableList tableData=FXCollections.observableArrayList();
//生成虚拟数据。
对于(int i=0;i<100;i++){
ObservableList行=FXCollections.observableArrayList();
对于(int j=0;j{
//我们需要得到所选行和表列的索引
//在要编辑的列索引上。
int selectedRowIndex=table.getSelectionModel().getSelectedIndex();
编辑(selectedRowIndex,table.getColumns().get(1));
});
ContextMenu=新建ContextMenu(编辑项);
table.setContextMenu(菜单);
场景=新场景(表);
舞台场景;
stage.show();
}
/**
*返回一个简单列。
*/
私有表列addColumn(int索引,字符串名称){
TableColumn col=新的TableColumn(名称);
col.setCellValueFactory(e->new SimpleStringProperty(e.getValue().get(index));
返回列;
}
/**
*返回一个可编辑的列。
*/
私有TableColumn addEditableColumn(整数索引,字符串名称){
TableColumn col=新的TableColumn(名称);
col.setCellValueFactory(e->new SimpleStringProperty(e.getValue().get(index));
col.setCellFactory(TextFieldTableCell.forTableColumn());
col.setOnEditCommit(新的EventHandler(){
@凌驾
公共无效句柄(CellEditEvent t){
((ObservableList)t.getTableView().getItems().get(t.getTablePosition().getRow()).set(索引,
t、 getNewValue());
}
});
返回列;
}
公共静态void main(字符串[]args){
发射();
}
}

谢谢Fabian。您的解决方案在定制CellEditing过程方面非常好!我将在下一个项目中尝试。你好,Jonatan,是的,你完全理解我的问题。非常感谢您的解决方案!使用
table.edit(selectedRowIndex,table.getColumns().get(1))真的帮助我解决了我的案子。在此之前,我的代码是
tbl.getSelectionModel().select(currentRow,colCardTotal)仅当选择了一行并按下Enter键以使TableView进入编辑模式时,该选项才起作用。
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;
    };
}
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();
    }
}