Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
179 views
in Technique[技术] by (71.8m points)

JavaFX 11 TableView Cell navigation by TAB key pressed without custom editableCell class

The problem:

I want to navigate through a TableView from one cell to the next right neighbor cell in JavaFX by using the TAB key.

Notice: The TableView is set to editable. And CellSelection is enabled too.

 tableReceipt.getSelectionModel().setCellSelectionEnabled(true);

The handling of the KeyPressedEvent seemingly is not my problem, but to request the focus of the single cell on the right of the current cell.

I can focus one cell but when i press the TAB key the focus goes out of the table on other form elements.

The TableView contains some editable TextFieldTableCells and one editable ComboBoxTableCell.

I don't use a custom class for the editable Cells but Code like this:

Callback<TableColumn<Receipt, int>, TableCell<Receipt, int>> tfCallBack = TextFieldTableCell.forTableColumn();
columnAmount.setCellFactory(tfCallBack);

for a TableCell with editable TextField nature.

My question:

How can I implement a solution to solve my problem? A theoretical solution would help too. I allready searched for this topic but only found an example that's using a custom EditableCell class. I think there must be a solution using the callback method like I do.

Solution approach:

tableReceipt.setOnKeyPressed(new EventHandler<KeyEvent>() {
    @Override
    public void handle(KeyEvent t) {
        if (t.getCode() == KeyCode.TAB) {
            tableReceipt.getFocusModel().focusRightCell();
            Robot r = new Robot();
            r.keyPress(KeyCode.ENTER);
         }
     }
});

With this code I can get focus of the right cell next to the current one. And I need the ENTER KeyPress to enable the editable mode of the Cell. But when I press TAB on keyboard the new value is not committed. For example I press '2' the default value is '0' and after pressing TAB the value is again '0'.

Question No.2:

How can I combine the code above with a changeListener/onEditCommitListener, that the new value is stored in the cell after pressing TAB?

Thank you.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This may be helpful. You have to manually call it after you complete a cell edit.

import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

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

/**
 * Created by Brian Boutin on 5/14/2019
 */

class CellNav<T> {

    private final TableView<T> tableView;
    private KeyEvent lastKeyEvent;
    private TablePosition editingPosition;

    CellNav(TableView<T> tableView) {
        this.tableView = tableView;
        this.editingPosition = null;

        tableView.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
            if (event.getCode() == KeyCode.TAB || event.getCode() == KeyCode.ENTER) {
                editingPosition = tableView.getEditingCell();
                lastKeyEvent = event;
            }
        });

        tableView.setOnMouseReleased(e -> editingPosition = null);

        for (TableColumn col : tableView.getColumns()) {
            col.setOnEditCancel(event -> editingPosition = null);
        }
    }

    void doCellNav() {
        if (editingPosition == null) {
            return;
        }

        if (lastKeyEvent.getCode() == KeyCode.ENTER) {

            int selectIdx;
            if (lastKeyEvent.isShiftDown()) {
                selectIdx = editingPosition.getRow() - 1;
            } else {
                selectIdx = editingPosition.getRow() + 1;
            }

            if (selectIdx < 0 ) {
                selectIdx = tableView.getItems().size() - 1;

            } else if (selectIdx > tableView.getItems().size() - 1) {
                selectIdx = 0;
            }

            tableView.layout();
            tableView.scrollTo(selectIdx == 0 ? selectIdx : selectIdx - 1);
            tableView.getSelectionModel().clearAndSelect(selectIdx);
            tableView.edit(selectIdx, editingPosition.getTableColumn());

        } else if (lastKeyEvent.getCode() == KeyCode.TAB) {
            TableColumn colToEdit = getNextColumn(!lastKeyEvent.isShiftDown(), editingPosition.getTableColumn());
            if (colToEdit != null) {
                tableView.layout();
                tableView.scrollToColumn(colToEdit);
                tableView.edit(editingPosition.getRow(), colToEdit);
            }
        }

        editingPosition = null;
    }

    boolean isNavigating() {
        return editingPosition != null;
    }

    private TableColumn getNextColumn(boolean forward, TableColumn currentCol) {
        List<TableColumn> columns = new ArrayList<>();
        for (TableColumn col : tableView.getColumns()) {
            if (col.isEditable() && col.isVisible() && (col.getStyleClass().contains("editable-col") || col.getStyleClass().contains("result-col"))) {
                columns.add(col);
            }
        }

        if (columns.size() < 2) {
            return null;
        }

        int currentIndex = -1;
        for (int i = 0; i < columns.size(); i++) {
            if (columns.get(i) == currentCol) {
                currentIndex = i;
                break;
            }
        }
        int nextIndex = currentIndex;
        if (forward) {
            nextIndex++;
            if (nextIndex > columns.size() - 1) {
                nextIndex = 0;
            }
        } else {
            nextIndex--;
            if (nextIndex < 0) {
                nextIndex = columns.size() - 1;
            }
        }
        return columns.get(nextIndex);
    }
}


public class ExampleClass{
  CellNav cellNav;
  
  public ExampleClass() {
    TableView  yourTableView = new TableView();
    cellNav = new CellNav(yourTableView);

    TableColumn someCol = new TableColumn();
    someCol.setOnEditCommit(e -> {

     //perform a save of your table data here

       //pick up cell nav again
      if (cellNav.isNavigating()) {
        cellNav.doCellNav();
      }
    });
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...