JavaFX 11通过按TAB键进行TableView单元格导航,无需自定义editableCell类

JavaFX 11通过按TAB键进行TableView单元格导航,无需自定义editableCell类,javafx,tabs,navigation,tableview,focus,Javafx,Tabs,Navigation,Tableview,Focus,问题: tableReceipt.setOnKeyPressed(new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent t) { if (t.getCode() == KeyCode.TAB) { tableReceipt.getFocusModel().focusRightCell(); Robot r = new Ro

问题:

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);
         }
     }
});
在JavaFX中,我想使用TAB键在TableView中从一个单元格导航到下一个右邻居单元格

注意:TableView设置为“可编辑”。而且CellSelection也已启用

 tableReceipt.getSelectionModel().setCellSelectionEnabled(true);
按键事件的处理似乎不是我的问题,而是请求当前单元格右侧单个单元格的焦点

我可以对一个单元格进行对焦,但当我按TAB键时,其他表单元素的对焦将从表中消失

TableView包含一些可编辑的TextFieldTableCell和一个可编辑的ComboBoxTableCell

我不为可编辑单元格使用自定义类,但代码如下:

Callback<TableColumn<Receipt, int>, TableCell<Receipt, int>> tfCallBack = TextFieldTableCell.forTableColumn();
columnAmount.setCellFactory(tfCallBack);
Callback tfCallBack=TextFieldTableCell.forTableColumn();
columnAmount.setCellFactory(tfCallBack);
对于具有可编辑文本字段性质的TableCell

我的问题:

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);
         }
     }
});
我如何实施解决方案来解决我的问题?理论上的解决方案也会有所帮助。我搜索了这个主题,但只找到了一个使用自定义EditableCell类的示例。我想一定有一个解决方案,像我一样使用回调方法

解决方案方法:

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);
         }
     }
});
TableReceivement.setOnKeyPressed(新的EventHandler(){
@凌驾
公共无效句柄(KeyEvent t){
if(t.getCode()==KeyCode.TAB){
TableReceive.getFocusModel().focusRightCell();
机器人r=新机器人();
r、 按键(KeyCode.ENTER);
}
}
});
通过这段代码,我可以获得当前单元格旁边正确单元格的焦点。我需要按ENTER键来启用单元格的可编辑模式。但当我按键盘上的TAB键时,新值未提交。例如,我按“2”时,默认值为“0”,按TAB后,该值再次为“0”

第二个问题:

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);
         }
     }
});
我如何将上面的代码与changeListener/onEditCommitListener组合,即按下TAB键后新值存储在单元格中


谢谢。

这可能会有帮助。您必须在完成单元格编辑后手动调用它

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();
      }
    });
  }
}
导入javafx.scene.control.TableColumn;
导入javafx.scene.control.TablePosition;
导入javafx.scene.control.TableView;
导入javafx.scene.input.KeyCode;
导入javafx.scene.input.KeyEvent;
导入java.util.ArrayList;
导入java.util.List;
/**
*Brian Boutin于2019年5月14日创作
*/
类CellNav{
私有最终TableView TableView;
私钥事件lastKeyEvent;
私有表位置编辑位置;
CellNav(TableView TableView){
this.tableView=tableView;
this.editingPosition=null;
tableView.addEventFilter(按下KeyEvent.KEY,事件->{
if(event.getCode()==KeyCode.TAB | | event.getCode()==KeyCode.ENTER){
editingPosition=tableView.getEditingCell();
lastKeyEvent=事件;
}
});
tableView.setOnMouseReleased(e->editingPosition=null);
for(TableColumn列:tableView.getColumns()){
col.setOnEditCancel(事件->编辑位置=null);
}
}
void doCellNav(){
if(editingPosition==null){
返回;
}
if(lastKeyEvent.getCode()==KeyCode.ENTER){
int-selectIdx;
if(lastKeyEvent.isShiftDown()){
选择IDX=editingPosition.getRow()-1;
}否则{
选择IDX=editingPosition.getRow()+1;
}
如果(选择IDX<0){
选择IDX=tableView.getItems().size()-1;
}else if(选择idx>tableView.getItems().size()-1){
选择IDX=0;
}
tableView.layout();
滚动到(selectIdx==0?selectIdx:selectIdx-1);
tableView.getSelectionModel().clearAndSelect(selectIdx);
编辑(selectIdx,editingPosition.getTableColumn());
}else if(lastKeyEvent.getCode()==KeyCode.TAB){
TableColumn colToEdit=getNextColumn(!lastKeyEvent.IsShift Down(),editingPosition.getTableColumn());
if(colToEdit!=null){
tableView.layout();
tableView.scrollToColumn(colToEdit);
编辑(editingPosition.getRow(),colToEdit);
}
}
编辑位置=空;
}
布尔值(){
返回编辑位置!=null;
}
专用TableColumn getNextColumn(布尔向前,TableColumn currentCol){
列表列=新的ArrayList();
for(TableColumn列:tableView.getColumns()){
如果(列isEditable()和列isVisible()&(列getStyleClass()包含(“可编辑列”)| |列getStyleClass()包含(“结果列”)){
列。添加(列);
}
}
if(columns.size()<2){
返回null;
}
int currentIndex=-1;
对于(int i=0;icolumns.size()-1){
nextIndex=0;
}
}否则{
下一个索引--;
如果(nextIndex<0){
nextIndex=columns.size()-1;
}
}
返回columns.get(nextIndex);
}
}
公共类示例类{
CellNav CellNav;
公共示例类(){
TableView yourTableView=新建TableView();
cellNav=新的cellNav(yourTableView);
TableColumn someCol=新TableColumn();
someCol.setOnEditCommit(e->{
//在此处保存表格数据
//再次拿起手机导航
if(cellNav.isNavigating()){
cellNav.doCellNav();