如何 select 并使用鼠标单击 ContextMenu 的 MenuItem 在 TableView 中编辑 TabelCell - JavaFX
Howto select and edit TabelCell in TableView with mouseclick on a MenuItem of ContextMenu - JavaFX
是否有可能 select 并在 TableView
中单击鼠标或按下 [=14= 的某个 MenuItem
后编辑 TableCell
=]?默认 TextFieldTableCell
实现仅支持在 TableRow
具有焦点时按 Enter 键或直接单击相应的单元格以 select 并编辑其内容。
您可以通过扩展 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();
}
请注意,这删除了 "standard" 进入编辑模式的方式。如果你不需要这个功能,你可以简单地使用一个 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;
};
}
如果正确理解你的问题,是的,你可以做到这一点。下面是一个示例,您可以使用上下文菜单编辑第二列中的单元格:
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();
}
}
是否有可能 select 并在 TableView
中单击鼠标或按下 [=14= 的某个 MenuItem
后编辑 TableCell
=]?默认 TextFieldTableCell
实现仅支持在 TableRow
具有焦点时按 Enter 键或直接单击相应的单元格以 select 并编辑其内容。
您可以通过扩展 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();
}
请注意,这删除了 "standard" 进入编辑模式的方式。如果你不需要这个功能,你可以简单地使用一个 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;
};
}
如果正确理解你的问题,是的,你可以做到这一点。下面是一个示例,您可以使用上下文菜单编辑第二列中的单元格:
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();
}
}