【问题标题】:TableVew - Select and focus clicked cellTableVew - 选择并聚焦单击的单元格
【发布时间】: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


【解决方案1】:

试试这个:

TableCell tc = (TableCell) event.getSource();
int index = tc.getIndex();

【讨论】:

  • 我试过了。问题在于它给出了已经聚焦/选择的单元格。我正在尝试获取尚未选择/聚焦的单元格索引,但单击的单元格又触发了事件。这里的问题是触发事件的表点击。必须有一种方法可以获取在引发事件时悬停的 TableCell。
  • 您是想通过单击编辑填充单元格还是编辑空白单元格?
  • 我试图改变点击单元格的焦点(即使单元格是空的,即它不可点击)。单击单元格时,无论其是否为空,都可以获得索引。我设法开始工作的方式(虽然我认为这不是一个好方法),听一个点击事件。如果单元格为空,则添加空数据(这可能是空字符串,具体取决于单元格接受的数据)。然后将焦点更改为单击的单元格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-13
  • 1970-01-01
相关资源
最近更新 更多