Java 有没有办法更改TableView焦点的可遍历行为?

Java 有没有办法更改TableView焦点的可遍历行为?,java,javafx,tableview,right-to-left,Java,Javafx,Tableview,Right To Left,我有一个简单的表视图,具有从右到左的节点方向和setCellSelectionEnabled(true)。现在,当按下工作台上的右箭头键时,焦点可遍历作用于另一侧,因此将选择左侧单元格。另一方面也是如此;按下向左箭头键时,将选择右侧单元格。出于区域目的,TableView的节点方向属性必须保持RTL。那么我该如何解决这个问题呢 以下是TableView FXML代码: <TableView fx:id="table" editable="true" layoutX="97.0" layou

我有一个简单的表视图,具有从右到左的节点方向和setCellSelectionEnabled(true)。现在,当按下工作台上的右箭头键时,焦点可遍历作用于另一侧,因此将选择左侧单元格。另一方面也是如此;按下向左箭头键时,将选择右侧单元格。出于区域目的,TableView的节点方向属性必须保持RTL。那么我该如何解决这个问题呢

以下是TableView FXML代码:

<TableView fx:id="table" editable="true" layoutX="97.0" layoutY="170.0" nodeOrientation="RIGHT_TO_LEFT" prefHeight="400.0" prefWidth="816.0" AnchorPane.bottomAnchor="25.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="121.0">
         <placeholder>
            <Label text="داده ای یافت نشد :(" />
         </placeholder>
         <columns>
            <TableColumn fx:id="numberColumn" maxWidth="120.0" minWidth="80.0" text="ردیف" />
            <TableColumn fx:id="nameColumn" maxWidth="400.0" minWidth="300.0" prefWidth="300.0" text="نام ماده اولیه" />
            <TableColumn fx:id="categoryColumn" maxWidth="300.0" minWidth="150.0" prefWidth="150.0" text="دسته بندی" />
            <TableColumn fx:id="priceColumn" maxWidth="300.0" minWidth="220.0" prefWidth="220.0" text="قیمت هر کیلوگرم(ریال)" />
            <TableColumn fx:id="unitColumn" maxWidth="200.0" minWidth="100.0" prefWidth="100.0" text="واحد" />
            <TableColumn fx:id="numberOfUsesColumn" maxWidth="120.0" minWidth="120.0" prefWidth="120.0" text="دفعات استفاده" />
            <TableColumn fx:id="deleteRowColumn" maxWidth="90.0" minWidth="90.0" prefWidth="90.0" resizable="false" text="حذف سطر" />
         </columns>
         <columnResizePolicy>
            <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
         </columnResizePolicy>
</TableView>

在表导航中不考虑RTL是一个错误

在那之前,我们可以进行黑客攻击(假设我们被允许进行攻击,即使用反射来访问TableViewSkin中的私有字段,使用内部api和实现细节;)

  • 获取表的外观(通常在显示表后可用)并访问其内部字段行为
  • 从行为的输入映射中获取左/右键映射并删除它们
  • 使用各自的事件处理程序将键交叉连接到处理程序并添加它们
在代码中,类似于(此处仅适用于左/右,需要对带有修饰符的映射执行相同的操作):

protected void hackNavigation(表视图表){
TableViewSkin皮肤=(TableViewSkin)table.getSkin();
//反射式访问私有字段
//使用您自己喜欢的实用程序方法:)
TableViewBehavior=(TableViewBehavior)
FXUtils.invokeGetFieldValue(TableViewSkin.class,皮肤,“行为”);
//访问映射

ObservableList这是一个bug,在fx15中已修复-在此之前,请查看TableViewBehaviorBase:替换左/右键映射以考虑方向(这是内部api,但相当稳定-因此调整应该继续工作)这是一个bug链接:(顺便说一句,只是吹毛求疵:这不是焦点遍历,而是正常导航:)@kleopatra谢谢:((我现在使用的是OpenJDK 15 ea+3。谢谢。你是说openjfx,不是吗:)对不起,我对这个问题很困惑,对不起,是的openjfx 15 ea+3:|
protected void hackNavigation(TableView<?> table) {
    TableViewSkin<?> skin = (TableViewSkin<?>) table.getSkin();
    // access private field reflectively 
    // use your own favorite utility method :)
    TableViewBehavior<?> behavior = (TableViewBehavior<?>) 
            FXUtils.invokeGetFieldValue(TableViewSkin.class, skin, "behavior");
    // access mappings
    ObservableList<Mapping<?>> mappings = behavior.getInputMap().getMappings();
    // lookup the original mappings for left/right
    KeyBinding leftBinding = new KeyBinding(KeyCode.LEFT);
    KeyBinding rightBinding = new KeyBinding(KeyCode.RIGHT);
    KeyMapping leftMapping = getMapping(mappings, leftBinding); 
    KeyMapping rightMapping = getMapping(mappings, rightBinding);
    // remove the original mappings
    mappings.removeAll(leftMapping, rightMapping);
    // create new mappings with the opposite event handlers and add them
    KeyMapping replaceRight = new KeyMapping(rightBinding, leftMapping.getEventHandler());
    KeyMapping replaceLeft = new KeyMapping(leftBinding, rightMapping.getEventHandler());
    mappings.addAll(replaceRight, replaceLeft);
}

/**
 * Utility method to get hold of a KeyMapping for a binding. 
 * Note: only use if certain that it is contained, or guard against failure 
 */
protected KeyMapping getMapping(ObservableList<Mapping<?>> mappings, KeyBinding keyBinding) {
    Optional<KeyMapping> opt = mappings.stream()
            .filter(mapping -> mapping instanceof KeyMapping)
            .map(mapping -> (KeyMapping) mapping)
            .filter(keyMapping -> keyMapping.getMappingKey().equals(keyBinding))
            .findAny()
            ;
    return opt.get();
}

// useage
stage.show();
hackNavigation(myTable);