TableView - 编辑聚焦的单元格 [英] TableView - Edit focused cell

查看:203
本文介绍了TableView - 编辑聚焦的单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个监听键盘事件的事件监听器。当我尝试通过使用按键事件进入编辑模式,出于某种奇怪的原因,一个不正确的单元格进入编辑模式。



例如,我想编辑一个单元格。我使用键盘箭头去我想编辑的单元格,即被聚焦的单元格。通过点击键盘上的字母,聚焦的单元格应该进入编辑模式。当我尝试编辑聚焦单元格时,错误的单元格进入编辑模式。

  private final class EditCell extends TableCell< SimpleStringProperty,String> ;实现GenericTable 
{
$ b $公共EditCell()
{
//添加事件列表。 table是一个TableView
table.setOnKeyPressed(keyEvent - > this.handleKeyPressed(keyEvent)); (key.getCode()。isLetterKey())


$ b $公共无效handleKeyPressed(KeyEvent键)
{
//键盘事件
b $ b {
if(!this.isEditing())
{

this.edit = true;

//焦点索引
int focusIndex = this.table.getSelectionModel()。getFocusedIndex();

this.changeTableCellFocus(this.table,focusIndex);

this.startEdit();




$ b // startEdit()函数
@Override
public void startEdit()

if(this.edit)
{
LOGGER.info(开始编辑单元格索引:+ this.getIndex());
super.startEdit();
this.createTextField();
this.setText(null);
this.setGraphic(this.textField);
this.textField.selectAll();
this.textField.requestFocus();

this.textField.setOnKeyPressed(keyEvent - > this.handleKeyPressed(keyEvent));

this.textField.focusedProperty()
.addListener((observable,oldValue,newValue) - > this.onTextFieldFocusChange(observable,
oldValue,
newValue) );


$ b $ //改变焦点
public void changeTableCellFocus(final TableView<> table,final int focusIndex)
{
table.requestFocus();
table.getSelectionModel()。clearAndSelect(focusIndex);
table.getFocusModel()。focus(focusIndex);




$ b $ p
$ b

在进入编辑模式之前,我把焦点改变为点击单元格,然后调用startEdit()方法。我试图调试的问题,但没有运气。我注意到focusIndex与当前单元格索引不同。我不确定为什么索引是不同的。

解决方案

你的代码的问题是每个单元格都调用 table.setOnKeyPressed(...),因为它被创建。这与任何其他 set 方法一样,所以表中的 keyPressed 处理程序只设置为最后一个 EditCell 创建。你不能控制单元格的实际创建,这不一定(也不可能)成为单元格的焦点。



TableView 有足够的API可以直接从表中管理。特别是

  table.getFocusModel()。getFocusedCell()

会给你一个 TablePosition 来表示当前聚焦的单元格。从那里你可以检索相应的行索引和 TableColumn 。然后你只需要调用 table.edit(int row,TableColumn< ...> column); 来指示合适的单元进入编辑模式。 >

下面是一个完整的例子。我没有花费很多精力在文本字段中选择文本等方面做出漂亮的编辑,你可能想要以某种方式实现编辑取消,但这应该让你开始。

  import java.util.ArrayList; 
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
导入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 {

$ b @Override
public void start(Stage primaryStage){
TableView< List< StringProperty> > table = new TableView<>();
table.getSelectionModel()。setCellSelectionEnabled(true);
table.setEditable(true); (int i = 0; i <10; i ++){
table.getColumns()。add(createColumn(i));



List< StringProperty> rowData = new ArrayList<>();
table.getItems()。add(rowData); (int j = 0; j <10; j ++){
rowData.add(new SimpleStringProperty(String.format(Cell [%d,%d],i,j)) );



table.setOnKeyTyped(event - > {
TablePosition< List< StringProperty> ;, String> focusedCell = table.getFocusModel()。getFocusedCell );
if(focusedCell!= null){
table.getItems()。get(focusedCell.getRow())。get(focusedCell.getColumn())。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< List< StringProperty>,String> createColumn(int colIndex){
TableColumn< List< StringProperty>,String> col = new TableColumn<>(Column+ colIndex);
col.setCellValueFactory(cellData - > cellData.getValue()。get(colIndex));
col.setCellFactory(column - > new EditCell());
return col;
}

private static class EditCell extends TableCell< List< StringProperty> String> {

private final TextField textField = new TextField();

EditCell(){
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);
setContentDisplay(ContentDisplay.TEXT_ONLY);



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


I have an event listener that listens for keyboard events. When i try to enter edit mode by using key event, for some strange reason an incorrect cell enters edit mode.

For example I want to edit a cell. I use keyboard arrows to go to the cell I want to edit i.e. the cell that is focused. By clicking a letter on the keyboard, the focused cell should enter edit mode. When I try to edit the focused cell, the wrong cell enters edit mode.

private final class EditCell extends TableCell<SimpleStringProperty, String> implements GenericTable
{

    public EditCell()
    {
        // Add event listsner. table is a TableView
        table.setOnKeyPressed(keyEvent -> this.handleKeyPressed(keyEvent));
    }

    public void handleKeyPressed(KeyEvent key)
    {
        // Keyboard events
        if (key.getCode().isLetterKey())
        {
            if (!this.isEditing())
            {

                this.edit = true;

                // focus index
                int focusIndex = this.table.getSelectionModel().getFocusedIndex();

                this.changeTableCellFocus(this.table, focusIndex);

                this.startEdit();
            }
        }
    }


    // startEdit() function
    @Override
    public void startEdit()
    {
        if (this.edit)
        {
            LOGGER.info("Start editing on cell index: " + this.getIndex());
            super.startEdit();
            this.createTextField();
            this.setText(null);
            this.setGraphic(this.textField);
            this.textField.selectAll();
            this.textField.requestFocus();

            this.textField.setOnKeyPressed(keyEvent -> this.handleKeyPressed(keyEvent));

            this.textField.focusedProperty()
                    .addListener((observable, oldValue, newValue) -> this.onTextFieldFocusChange(observable,
                            oldValue,
                            newValue));
        }
    }

    // Change focus
    public void changeTableCellFocus(final TableView<?> table, final int focusIndex)
    {
        table.requestFocus();
        table.getSelectionModel().clearAndSelect(focusIndex);
        table.getFocusModel().focus(focusIndex);
    }
}

Before entering edit mode, I change focus to the clicked cell and then call the startEdit() method. I have attempted to debug the issue but with no luck. I have noticed that the focusIndex is different from the current cell index. I'm not sure why the index is different.

解决方案

The problem with your code is that every cell is calling table.setOnKeyPressed(...) as it is created. This works like any other set method, so the keyPressed handler on the table is just set to the one from the last EditCell that was created. You have no control over actual creation of cells, and this is not necessarily (and unlikely) to be the cell that happens to be focused.

The TableView has enough API for you to be able to manage this directly from the table. In particular

table.getFocusModel().getFocusedCell()

will give you a TablePosition representing the currently focused cell. From that you can retrieve the corresponding row index and TableColumn. Then you just need to call table.edit(int row, TableColumn<...> column); to instruct the appropriate cell to go into editing mode.

Here's a complete example. I didn't make much effort to make the editing "pretty" in terms of selecting text etc in the text field, and you might want to implement edit cancel somehow, but this should get you started.

import java.util.ArrayList;
import java.util.List;

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<List<StringProperty>> table = new TableView<>();
        table.getSelectionModel().setCellSelectionEnabled(true);
        table.setEditable(true);

        for (int i = 0; i < 10; i++) {
            table.getColumns().add(createColumn(i));

            List<StringProperty> rowData = new ArrayList<>();
            table.getItems().add(rowData);
            for (int j = 0; j < 10 ; j++) {
                rowData.add(new SimpleStringProperty(String.format("Cell [%d, %d]", i, j)));
            }
        }

        table.setOnKeyTyped(event -> {
            TablePosition<List<StringProperty>, String> focusedCell = table.getFocusModel().getFocusedCell();
            if (focusedCell != null) {
                table.getItems().get(focusedCell.getRow()).get(focusedCell.getColumn()).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<List<StringProperty>, String> createColumn(int colIndex) {
        TableColumn<List<StringProperty>, String> col = new TableColumn<>("Column "+colIndex);
        col.setCellValueFactory(cellData -> cellData.getValue().get(colIndex));
        col.setCellFactory(column -> new EditCell());
        return col ;
    }

    private static class EditCell extends TableCell<List<StringProperty>, String> {

        private final TextField textField = new TextField();

        EditCell() {   
            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);
            setContentDisplay(ContentDisplay.TEXT_ONLY);
        }

    }

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

这篇关于TableView - 编辑聚焦的单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆