【发布时间】:2015-04-14 06:51:08
【问题描述】:
我在 TableView 上有一个事件侦听器,用于侦听鼠标事件。引发鼠标事件时,如何获取鼠标单击的单元格索引(并将焦点更改为新单元格)。
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
}
}
}
}
当鼠标事件在单元格上而不是在表格上时,我已设法获取单击的单元格索引。
下面的代码可以用来获取事件在Cell上时被点击的cell索引。当鼠标事件在 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", "jacob.smith@example.com"));
this.observableListOfPerson.add(new Person("Isabella", "Johnson", "isabella.johnson@example.com"));
this.observableListOfPerson.add(new Person("Ethan", "Williams", "ethan.williams@example.com"));
this.observableListOfPerson.add(new Person("Emma", "Jones", "emma.jones@example.com"));
this.observableListOfPerson.add(new Person("Michael", "Brown", "michael.brown@example.com"));
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);
}
}
【问题讨论】:
-
通常,如果您想通过鼠标单击获得有关单元格的信息,您可以在单元格上注册鼠标侦听器。你能解释更多“只需单击一下就不会发生任何事情”(也许创建一个简单、完整的示例来显示问题)。如果我为单击表格单元格注册鼠标侦听器,它会将当前焦点单元格显示为该单元格。
-
我可以获得当前选中/聚焦的单元格。我还可以获得索引或单击的单元格。问题是当我尝试将焦点更改为单击的索引单元格时。它不会将焦点更改为单击的索引单元格。我认为问题与单元格是空的事实有关。所以我尝试在单击单元格时添加一个对象。还是一样的问题。
-
是的,您在这里突破了
TableView的预期用例的限制。TableView旨在作为一组数据的视图,您可以对其进行操作。在这种情况下,将焦点放在一个空的单元格上是没有意义的,而且通常 API 不支持这一点。您的解决方法(向数据模型添加新元素)有点问题:由于单元重用,无法真正保证添加新数据会导致当前单元格用于表示正确的数据。
标签: java javafx mouseevent tableview javafx-8