Java TableVew-抛出KeyEvent时编辑单元格
我在TableView上有一个事件侦听器,用于侦听键盘事件Java TableVew-抛出KeyEvent时编辑单元格,java,javafx,focus,tableview,Java,Javafx,Focus,Tableview,我在TableView上有一个事件侦听器,用于侦听键盘事件 // Add event listener to table table.setOnKeyTyped(event -> { TablePosition<SimpleStringProperty, String> focusedCell = table.getFocusModel().getFocusedCell(); if (focusedCell != null)
// Add event listener to table
table.setOnKeyTyped(event -> {
TablePosition<SimpleStringProperty, String> focusedCell = table.getFocusModel().getFocusedCell();
if (focusedCell != null)
{
table.getItems().get(focusedCell.getRow()).set(event.getCharacter());
table.edit(focusedCell.getRow(), focusedCell.getTableColumn());
}
});
//将事件侦听器添加到表中
表.setOnKeyTyped(事件->{
TablePosition focusedCell=table.getFocusModel().getFocusedCell();
if(focusedCell!=null)
{
table.getItems().get(focusedCell.getRow()).set(event.getCharacter());
编辑(focusedCell.getRow(),focusedCell.getTableColumn());
}
});
当用户单击enter或将焦点更改为另一个单元格时,我在使用新数据更新单元格时遇到问题。单击“输入”或“更改焦点”时,单元格将变为空。我不知道为什么。如何保存数据并使用新数据更新单元格
// Here is the full code.
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TableViewEdit extends Application
{
@Override
public void start(Stage primaryStage)
{
TableView<SimpleStringProperty> table = new TableView<SimpleStringProperty>();
table.getSelectionModel().setCellSelectionEnabled(true);
table.setEditable(true);
table.getColumns().add(this.createColumn());
ObservableList<SimpleStringProperty> rowData = FXCollections.observableArrayList();
//table.getItems().addAll(rowData);
for (int j = 0; j < 10; j++)
{
rowData.add(new SimpleStringProperty(String.format("Cell [%d", j)));
}
table.setItems(rowData);
table.setOnKeyTyped(event -> {
TablePosition<SimpleStringProperty, String> focusedCell = table.getFocusModel().getFocusedCell();
if (focusedCell != null)
{
table.getItems().get(focusedCell.getRow()).set(event.getCharacter());
table.edit(focusedCell.getRow(), focusedCell.getTableColumn());
}
});
Scene scene = new Scene(new BorderPane(table), 880, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private TableColumn<SimpleStringProperty, String> createColumn()
{
TableColumn<SimpleStringProperty, String> col = new TableColumn<>("Column ");
col.setCellValueFactory(cellData -> cellData.getValue());
col.setCellFactory(column -> new EditCell());
return col;
}
private static class EditCell extends TableCell<SimpleStringProperty, String>
{
private final TextField textField = new TextField();
EditCell()
{
this.textProperty().bind(this.itemProperty());
this.setGraphic(this.textField);
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
this.textField.setOnAction(evt -> this.commitEdit(this.textField.getText()));
this.textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (!isNowFocused)
{
this.commitEdit(this.textField.getText());
}
});
}
@Override
public void startEdit()
{
super.startEdit();
this.textField.setText(this.getItem());
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
this.textField.requestFocus();
}
@Override
public void cancelEdit()
{
super.cancelEdit();
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
@Override
public void commitEdit(String text)
{
super.commitEdit(text);
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
public static void main(String[] args)
{
launch(args);
}
}
//下面是完整的代码。
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.scene.scene;
导入javafx.scene.control.ContentDisplay;
导入javafx.scene.control.TableCell;
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TablePosition;
导入javafx.scene.control.TableView;
导入javafx.scene.control.TextField;
导入javafx.scene.layout.BorderPane;
导入javafx.stage.stage;
公共类TableViewEdit扩展了应用程序
{
@凌驾
公共无效开始(阶段primaryStage)
{
TableView table=新TableView();
table.getSelectionModel().setCellSelectionEnabled(true);
table.setEditable(true);
table.getColumns().add(this.createColumn());
ObservableList rowData=FXCollections.observableArrayList();
//table.getItems().addAll(rowData);
对于(int j=0;j<10;j++)
{
添加(新的SimpleStringProperty(String.format(“单元格[%d],j));
}
表.集合项目(行数据);
表.setOnKeyTyped(事件->{
TablePosition focusedCell=table.getFocusModel().getFocusedCell();
if(focusedCell!=null)
{
table.getItems().get(focusedCell.getRow()).set(event.getCharacter());
编辑(focusedCell.getRow(),focusedCell.getTableColumn());
}
});
场景=新场景(新边框窗格(表),880600);
初级阶段。场景(场景);
primaryStage.show();
}
私有TableColumn createColumn()
{
TableColumn col=新的TableColumn(“列”);
col.setCellValueFactory(cellData->cellData.getValue());
col.setCellFactory(列->新建EditCell());
返回列;
}
私有静态类EditCell扩展了TableCell
{
私有最终文本字段TextField=新文本字段();
EditCell()
{
this.textProperty().bind(this.itemProperty());
this.setGraphic(this.textField);
this.setContentDisplay(仅限ContentDisplay.TEXT_);
this.textField.setOnAction(evt->this.committedit(this.textField.getText());
this.textField.focusedProperty().addListener((obs,waspoccused,isNowFocused)->{
如果(!isNowFocused)
{
this.committedit(this.textField.getText());
}
});
}
@凌驾
公开作废已启动IT()
{
super.startEdit();
this.textField.setText(this.getItem());
此.setContentDisplay(仅限ContentDisplay.GRAPHIC_);
this.textField.requestFocus();
}
@凌驾
公共作废取消编辑()
{
super.cancelEdit();
this.setContentDisplay(仅限ContentDisplay.TEXT_);
}
@凌驾
public void committedit(字符串文本)
{
超级。承诺(文本);
this.setContentDisplay(仅限ContentDisplay.TEXT_);
}
}
公共静态void main(字符串[]args)
{
发射(args);
}
}
这些问题变得非常棘手;我认为任何“行为相关”(即对用户输入做出反应的标准控件)都很难更改,而且JavaFX通常不支持这些问题。希望这是API的一个有待改进的领域
似乎存在两个不同的问题。我认为Enter键的情况是,尽管这会在文本字段上生成一个提交编辑等的ActionEvent
,但keyTyped
事件仍会传播回表中,导致它重新进入编辑模式。对此的修复方法似乎是使用而不是按下表上的处理程序(尽管老实说,这感觉不是很可靠)
代码依赖于表列上的默认onEditCommit
处理程序来实际更改属性值。onEditCommit
处理程序由默认表单元格的committedit
方法调用。调用committedit(…)的问题
失去焦点时,默认的CommittedIt
方法首先检查单元格是否处于编辑状态,如果不处于编辑状态,则什么也不做。看起来,当单元格失去焦点时,在调用focusProperty
侦听器之前,它会退出编辑状态,因此永远不会调用onEditCommit
处理程序(顺便说一句,这也会妨碍示例13-11“单元格编辑的替代解决方案”(sic)在JDK 8 u25(当前版本)中正常工作。)
对于第二个问题,我能看到的唯一修复方法是直接从committedit(…)
方法更新属性。这要求单元格引用属性,这打破了单元格和单元格值之间的良好分隔
我使用常见的Person
示例重写了该示例,并合并了这两个修复程序。该示例运行得非常好,尽管正如我所说的,有些部分感觉不太稳定:
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TableViewEditOnType extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Person> table = new TableView<>();
table.getSelectionModel().setCellSelectionEnabled(true);
table.setEditable(true);
table.getColumns().add(createColumn("First Name", Person::firstNameProperty));
table.getColumns().add(createColumn("Last Name", Person::lastNameProperty));
table.getColumns().add(createColumn("Email", Person::emailProperty));
table.getItems().addAll(
new Person("Jacob", "Smith", "jacob.smith@example.com"),
new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
new Person("Ethan", "Williams", "ethan.williams@example.com"),
new Person("Emma", "Jones", "emma.jones@example.com"),
new Person("Michael", "Brown", "michael.brown@example.com")
);
table.setOnKeyPressed(event -> {
TablePosition<Person, ?> pos = table.getFocusModel().getFocusedCell() ;
if (pos != null) {
table.edit(pos.getRow(), pos.getTableColumn());
}
});
Scene scene = new Scene(new BorderPane(table), 880, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private TableColumn<Person, String> createColumn(String title, Function<Person, StringProperty> property) {
TableColumn<Person, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setCellFactory(column -> new EditCell(property));
return col ;
}
private static class EditCell extends TableCell<Person, String> {
private final TextField textField = new TextField();
private final Function<Person, StringProperty> property ;
EditCell(Function<Person, StringProperty> property) {
this.property = property ;
textProperty().bind(itemProperty());
setGraphic(textField);
setContentDisplay(ContentDisplay.TEXT_ONLY);
textField.setOnAction(evt -> {
commitEdit(textField.getText());
});
textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (! isNowFocused) {
commitEdit(textField.getText());
}
});
}
@Override
public void startEdit() {
super.startEdit();
textField.setText(getItem());
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
textField.requestFocus();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
@Override
public void commitEdit(String text) {
super.commitEdit(text);
Person person = getTableView().getItems().get(getIndex()) ;
StringProperty cellProperty = property.apply(person);
cellProperty.set(text);
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
public static class Person {
private final StringProperty firstName = new SimpleStringProperty();
private final StringProperty lastName = new SimpleStringProperty();
private final StringProperty email = new SimpleStringProperty();
public Person(String firstName, String lastName, String email) {
setFirstName(firstName);
setLastName(lastName);
setEmail(email);
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final java.lang.String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final java.lang.String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final java.lang.String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final java.lang.String lastName) {
this.lastNameProperty().set(lastName);
}
public final StringProperty emailProperty() {
return this.email;
}
public final java.lang.String getEmail() {
return this.emailProperty().get();
}
public final void setEmail(final java.lang.String email) {
this.emailProperty().set(email);
}
}
public static void main(String[] args) {
launch(args);
}
}
import java.util.function.function;
导入javafx.application.application;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.scene.scene;
导入javafx.scene.control.ContentDisplay;
导入javafx.scene.control.TableCell;
导入javafx.scene.control.TableColumn;
接口信息处理器