编辑文本单元格时 Javafx TableView 滚动错误

Javafx TableView scrolling bug when editing text cell

当我在 Javafx TableView 中编辑文本字段单元格时,我注意到如果我使用鼠标滚轮滚动,它会将焦点更改到同一列中的另一个单元格。

这对我来说似乎是个错误。

在我的具体情况下,我设置了一个 table,我只希望某些行成为 editable。这通常工作正常,除非您可以通过单击编辑 editable 行然后滚动鼠标滚轮来颠覆此约束。这允许您然后编辑不应为 editable.

的行

这甚至可以通过 运行 来自 Oracle TableView docs

运行 示例并添加额外的行,直到它需要出现垂直滚动条。然后开始编辑一个单元格,用鼠标滚轮滚动

有人知道 fix/work 吗?

我是 运行 1.8。0_92

更新示例与说明:

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TableViewExample extends Application {

  private TableView<Person> table = new TableView<Person>();
  private ObservableList<Person> people = FXCollections.observableArrayList();

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

  public TableViewExample() {
    for (int id = 0; id < 100; id++) {
      people.add(new Person(String.valueOf(id)));
    }
  }

  @Override
  public void start(Stage stage) {
    Scene scene = new Scene(new Group());
    stage.setTitle("Table View Sample");

    table.setEditable(true);

    TableColumn idColumn = new TableColumn("Id");
    idColumn.setPrefWidth(400);
    idColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("id"));
    idColumn.setCellFactory(
          new Callback<TableColumn, TableCell>() {
            public TableCell call(TableColumn p) {
              return new EditingCell();
            }
          }
    );
    idColumn.setOnEditCommit(
          new EventHandler<CellEditEvent<Person, String>>() {
            @Override
            public void handle(CellEditEvent<Person, String> t) {
              Person person =
                    ((Person) t.getTableView().getItems().get(t.getTablePosition().getRow()));
              person.setId(t.getNewValue());
            }
          }
    );

    table.setItems(people);
    table.getColumns().addAll(idColumn);
    ((Group) scene.getRoot()).getChildren().addAll(table);
    stage.setScene(scene);
    stage.show();
  }

  public static class Person {

    private final SimpleStringProperty id;

    private Person(String id) {
      this.id = new SimpleStringProperty(id);
    }

    public String getId() {
      return id.get();
    }

    public void setId(String id) {
      this.id.set(id);
    }
  }

  class EditingCell extends TableCell<Person, String> {

    private TextField textField;

    public EditingCell() {
    }

    @Override
    public void startEdit() {
      if (!isEmpty()) {
        super.startEdit();
        createTextField();
        setText(null);
        setGraphic(textField);
        textField.selectAll();
      }
    }

    @Override
    public void cancelEdit() {
      super.cancelEdit();

      setText((String) getItem());
      setGraphic(null);
    }

    @Override
    public void updateItem(String item, boolean empty) {
      super.updateItem(item, empty);

      if (empty) {
        setText(null);
        setGraphic(null);
      } else {
        if (isEditing()) {
          if (textField != null) {
            textField.setText(getString());
          }
          setText(null);
          setGraphic(textField);
        } else {
          setText(getString());
          setGraphic(null);
        }
      }
    }

    private void createTextField() {
      textField = new TextField(getString());
      textField.setMinWidth(getWidth() - getGraphicTextGap() * 2);
      textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
        @Override
        public void changed(ObservableValue<? extends Boolean> arg0,
              Boolean arg1, Boolean arg2) {
          if (!arg2) {
            commitEdit(textField.getText());
          }
        }
      });
    }

    private String getString() {
      return getItem() == null ? "" : getItem();
    }
  }
}

运行宁示例:

单击以编辑单元格中的值

向下滚动鼠标滚轮,注意另一个单元格已在编辑模式下获得焦点

在我的例子中,以下代码解决了问题:

 table.addEventFilter(ScrollEvent.ANY, scrollEvent -> {
            table.refresh();

            // close text box
            table.edit(-1, null);
        });