У меня есть прослушиватель событий в TableView, который прослушивает события мыши. Как я могу получить индекс ячейки с щелчком мыши (и изменить фокус на новую ячейку), когда вызывается событие мыши.TableVew - Выделить ячейку с нажатой клавишей
public class PrnTableController
{
@FXML
private TableView<SimpleStringProperty> table;
@FXML
private TableColumn<SimpleStringProperty, String> data;
@FXML
private void initialize()
{
this.data.setCellValueFactory(cellData -> cellData.getValue());
this.data.setCellFactory(event -> new EditCell(this.observablePrnPropertyData, this.table));
// Add mouse Listener
this.table.setOnMouseClicked(event -> this.handleOnMouseClick(event));
}
private void handleOnMouseClick(MouseEvent event)
{
TableView tv = (TableView) event.getSource();
// TODO : get the mouse clicked cell index
int index = ???
if (event.getButton().equals(MouseButton.PRIMARY))
{
if (event.getClickCount() == 2)
{
LOGGER.info("Double clicked on cell");
final int focusedIndex = this.table.getSelectionModel().getFocusedIndex();
if (index == focusedIndex)
{
// TODO : Double click
}
}
else if (event.getClickCount() == 1)
{
// TODO : Single click
}
}
}
}
Мне удалось получить индекс щелкнутой ячейки, когда событие мыши находится в ячейке, но не в таблице.
Следующий код может использоваться для получения индекса щелкнутой ячейки, когда событие находится в Ячейке. У меня были проблемы с выбором и изменением фокуса, когда событие мыши находится на TabelCell. Фокус не изменяется в новой ячейке. Он изменяется, если вы дважды щелкните. Одним щелчком ничего не происходит. Я подозреваю, что потому, что у меня есть другие слушатели событий, могут быть конфликтующие события. У меня есть следующее событие в TableCell - setOnDragDetected, setOnMouseDragEntered и следующее событие в TableView - addEventFilter, setOnKeyPressed, setOnEditCommit.
TableCell<Map<String, SimpleStringProperty>, String> cell = (TableCell<Map<String, SimpleStringProperty>, String>) mouseEvent.getSource();
int index = cell.getIndex();
Вот пример проблемы. В основном, когда вы нажимаете на ячейку, вы можете видеть, что событие зарегистрировано, но ничего не происходит. Я имею в виду, что фокус меняется на недавно щелкнувшуюся ячейку.
public class TableViewEditOnType extends Application
{
private TableView<Person> table;
private ObservableList<Person> observableListOfPerson;
@Override
public void start(Stage primaryStage)
{
this.table = new TableView<>();
this.table.getSelectionModel().setCellSelectionEnabled(true);
this.table.setEditable(true);
TableColumn<Person, String> firstName = this.createColumn("First Name", Person::firstNameProperty);
TableColumn<Person, String> lastName = this.createColumn("Last Name", Person::lastNameProperty);
TableColumn<Person, String> email = this.createColumn("Email", Person::emailProperty);
this.table.getColumns().add(firstName);
this.table.getColumns().add(lastName);
this.table.getColumns().add(email);
this.observableListOfPerson = FXCollections.observableArrayList();
this.observableListOfPerson.add(new Person("Jacob", "Smith", "[email protected]"));
this.observableListOfPerson.add(new Person("Isabella", "Johnson", "[email protected]"));
this.observableListOfPerson.add(new Person("Ethan", "Williams", "ethan.wil[email protected]"));
this.observableListOfPerson.add(new Person("Emma", "Jones", "[email protected]"));
this.observableListOfPerson.add(new Person("Michael", "Brown", "[email protected]"));
this.table.getItems().addAll(this.observableListOfPerson);
firstName.setOnEditCommit(event -> this.editCommit(event, "firstName"));
lastName.setOnEditCommit(event -> this.editCommit(event, "lastName"));
email.setOnEditCommit(event -> this.editCommit(event, "email"));
this.table.setOnKeyPressed(event -> {
TablePosition<Person, ?> pos = this.table.getFocusModel().getFocusedCell();
if (pos != null)
{
this.table.edit(pos.getRow(), pos.getTableColumn());
}
});
Scene scene = new Scene(new BorderPane(this.table), 880, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private void editCommit(CellEditEvent<Person, String> event, String whatEdited)
{
if (whatEdited.equals("firstName"))
{
event.getTableView().getItems().get(event.getTablePosition().getRow()).setFirstName(event.getNewValue());
}
else if (whatEdited.equals("lastName"))
{
event.getTableView().getItems().get(event.getTablePosition().getRow()).setLastName(event.getNewValue());
}
else if (whatEdited.equals("email"))
{
event.getTableView().getItems().get(event.getTablePosition().getRow()).setEmail(event.getNewValue());
}
}
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, this.table, this.observableListOfPerson));
return col;
}
private static class EditCell extends TableCell<Person, String>
{
private final TextField textField = new TextField();
private final Function<Person, StringProperty> property;
private TableView table;
private ObservableList<Person> observableListOfPerson;
EditCell(Function<Person, StringProperty> property, TableView table, ObservableList<Person> observableListOfPerson)
{
this.property = property;
this.table = table;
this.observableListOfPerson = observableListOfPerson;
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());
}
});
// On mouse click event
this.setOnMouseClicked(mouseEvent -> this.handleCellMouseClick(mouseEvent));
}
private void handleCellMouseClick(final MouseEvent mouseEvent)
{
System.out.println("MOUSE EVENT");
TableCell<Map<String, SimpleStringProperty>, String> cell = (TableCell<Map<String, SimpleStringProperty>, String>) mouseEvent.getSource();
int index = cell.getIndex();
// Set up the map data structure before editing
this.validCell(index);
if (mouseEvent.getButton().equals(MouseButton.PRIMARY))
{
if (mouseEvent.getClickCount() == 2)
{
System.out.println("Double clicked on cell");
final int focusedIndex = this.table.getSelectionModel().getFocusedIndex();
if (index == focusedIndex)
{
this.changeTableCellFocus(this.table, index);
}
}
else if (mouseEvent.getClickCount() == 1)
{
System.out.println("Single click on cell");
this.changeTableCellFocus(this.table, index);
}
}
}
private void validCell(final int cellIndex)
{
if (cellIndex >= this.observableListOfPerson.size())
{
for (int x = this.observableListOfPerson.size(); x <= cellIndex; x++)
{
this.observableListOfPerson.add(new Person("", "", ""));
}
}
}
public void changeTableCellFocus(final TableView<?> table, final int focusIndex)
{
table.requestFocus();
table.getSelectionModel().clearAndSelect(focusIndex);
table.getFocusModel().focus(focusIndex);
}
@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);
Person person = this.getTableView().getItems().get(this.getIndex());
StringProperty cellProperty = this.property.apply(person);
cellProperty.set(text);
this.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)
{
this.setFirstName(firstName);
this.setLastName(lastName);
this.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);
}
}
Как правило, если вы хотите получить информацию о клетке с помощью мыши необходимо зарегистрировать слушателя мыши на ячейку. Можете ли вы объяснить больше «С одним щелчком ничего не происходит» (возможно, создайте простой, полный пример, показывающий проблему). Если я зарегистрирую прослушиватель мыши для щелчка на ячейке таблицы, он отображает текущую сфокусированную ячейку в качестве этой ячейки. –
Я могу получить текущую выбранную/сфокусированную ячейку. Я также могу получить индекс или щелкнув по ячейке. Проблема в том, что я пытаюсь изменить фокус на ячейку с щелчком. Он не меняет фокус на щелканную ячейку индекса. Я думаю, что проблема связана с тем, что ячейка пуста. Поэтому я попытался добавить объект при щелчке по ячейке. Еще одна проблема. – breaktop
Да, вы нажимаете границы предполагаемого прецедента «TableView» здесь. «TableView» предназначен для просмотра набора данных, с которыми вы можете манипулировать. В этом контексте нет смысла фокусироваться на ячейке, которая пуста, и, как правило, API не поддерживает это. Ваше обходное решение (добавление новых элементов в модель данных) немного проблематично: нет реальной гарантии того, что добавление новых данных приводит к тому, что текущая ячейка используется для представления правильных данных из-за повторного использования соты. –