JavaFX:使用组合键自定义遍历

时间:2013-10-04 13:04:42

标签: javafx-2

我有一个包含一个编辑组合框和三个可编辑文本字段的表格, 可编辑字段的创建方式如下:

public class EditingCell extends TableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
@Override
public void startEdit() {
    super.startEdit();
    if (textField == null) {
        createTextField();
    }
    setGraphic(textField);
    setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            textField.requestFocus();
            textField.selectAll();
        }
    });
}
@Override
public void cancelEdit() {
    super.cancelEdit();
    setText((String) getItem());
    setContentDisplay(ContentDisplay.TEXT_ONLY);
}
@Override
public void updateItem(String item, boolean empty) {
    super.updateItem(item, empty);
    if (empty) {
        setText(null);
        setGraphic(null);
    } else {
        if (isEditing()) {
            if (textField != null) {
                textField.setText(getString());
            }
            setGraphic(textField);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        } else {
            setText(getString());
            setContentDisplay(ContentDisplay.TEXT_ONLY);
        }
    }
}
private void createTextField() {
    textField = new TextField(getString());
    textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
    textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent t) {
            if (t.getCode() == KeyCode.ENTER) {
                commitEdit(textField.getText());
            } else if (t.getCode() == KeyCode.ESCAPE) {
                cancelEdit();
            } else if (t.getCode() == KeyCode.TAB) {
                commitEdit(textField.getText());
                TableColumn nextColumn = getNextColumn(!t.isShiftDown());
                if (nextColumn != null) {
                    getTableView().edit(getTableRow().getIndex(), nextColumn);
                }
            }
        }
    });
    textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            if (!newValue && textField != null) {
                commitEdit(textField.getText());
            }
        }
    });
}
private String getString() {
    return getItem() == null ? "" : getItem().toString();
}
/**
 *
 * @param forward true gets the column to the right, false the column to the left of the current column
 * @return
 */
private TableColumn<Person, ?> getNextColumn(boolean forward) {
    List<TableColumn<Person, ?>> columns = new ArrayList<>();
    for (TableColumn<Person, ?> column : getTableView().getColumns()) {
        columns.addAll(getLeaves(column));
    }
    //There is no other column that supports editing.
    if (columns.size() < 2) {
        return null;
    }
    int currentIndex = columns.indexOf(getTableColumn());
    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);
}

private List<TableColumn<Person, ?>> getLeaves(TableColumn<Person, ?> root) {
    List<TableColumn<Person, ?>> columns = new ArrayList<>();
    if (root.getColumns().isEmpty()) {
        //We only want the leaves that are editable.
        if (root.isEditable()) {
            columns.add(root);
        }
        return columns;
    } else {
        for (TableColumn<Person, ?> column : root.getColumns()) {
            columns.addAll(getLeaves(column));
        }
        return columns;
    }
}

}

可编辑的组合列创建如下:

public static void createEditingComboColumn(final TableColumn<DUMMY_PurchaseOrderLine, String> Column, final ObservableList<String>comboData, final ObservableList<DUMMY_PurchaseOrderLine> Pdata) {
 Column.setCellFactory(new Callback<TableColumn<DUMMY_PurchaseOrderLine,String>,TableCell<DUMMY_PurchaseOrderLine,String>>(){ 
 @Override
    public TableCell<DUMMY_PurchaseOrderLine, String> call(TableColumn<DUMMY_PurchaseOrderLine, String> p) {
    final TableCell<DUMMY_PurchaseOrderLine, String> cell = new TableCell<DUMMY_PurchaseOrderLine, String>(){
          @Override
           public void updateItem(String item, boolean empty) {
              if(item!=null){

             final  ComboBox editableComboBox = new ComboBox(comboData);
               editableComboBox.setEditable(true);
               editableComboBox.setMaxWidth(Double.MAX_VALUE);
               Platform.runLater(new Runnable() {
               @Override
                 public void run() {
                   editableComboBox.requestFocus();
                 }
               });
            setGraphic(editableComboBox);

          } 

         }
        };
    cell.addEventFilter(KeyEvent.KEY_PRESSED,new EventHandler<KeyEvent>(){
        @Override
        public void handle(KeyEvent t) {
            activeRow = cell.getIndex();
             if(t.getCode() == KeyCode.TAB||t.getCode() ==KeyCode.RIGHT){

                 cell.getTableView().edit(cell.getTableRow().getIndex(),cell.getTableView().getColumns().get(1) );

             } 
          }                
         }); 

         return cell;
        }
    }); 

}

问题:当我按任意列的TAB /右箭头键正常工作时,但是当我按下第二列的SHIFT + Tab /左箭头时,焦点熄灭。我如何使用键盘从第二列聚焦第一列(编辑组合)? 感谢....

1 个答案:

答案 0 :(得分:2)

以下关键事件处理程序中的条件

if (t.getCode() == KeyCode.TAB)

将处理“TAB”+任何修饰符,这意味着它将处理“Ctrl + TAB”,“Alt + TAB”,“Shift + Alt + TAB”等。“右”键也是如此。因此,仅处理“TAB”,首选方法是定义KeyCodeCombination 您发布的代码是部分的,不可执行的,即。 不是SSCCE 。据我所知,您的问题存在于关键事件处理中。因此,我写了一个完全不同的代码,但演示了上面提到的解释。参见示例,并尝试使用与“TAB”或“RIGHT”不同的组合键向前遍历。尝试使用“Ctrl + TAB”或“Alt + RIGHT”。按照预期,它对他们不起作用。

public class TraverseDemo extends Application {

    @Override
    public void start(Stage primaryStage) {
        final TextField textField1 = new TextField();
        final TextField textField2 = new TextField();
        final TextField textField3 = new TextField();

        // Diasble all traversals since we will manage them manually, for only textField2.
        textField1.setFocusTraversable(false);
        textField2.setFocusTraversable(false);
        textField3.setFocusTraversable(false);

        // Define key combinations for traversals.
        final KeyCombination kcTab = KeyCodeCombination.valueOf("TAB");
        final KeyCombination kcShiftTab = KeyCodeCombination.valueOf("Shift+TAB");
        final KeyCombination kcRight = KeyCodeCombination.valueOf("RIGHT");
        final KeyCombination kcLeft = KeyCodeCombination.valueOf("LEFT");

        // Default initial focused textfield
        requestFocus(textField2);

        textField2.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent t) {
                if (kcTab.match(t) || kcRight.match(t)) {
                    System.out.println("traverse forward");
                    requestFocus(textField3);
                } else if (kcShiftTab.match(t) || kcLeft.match(t)) {
                    System.out.println("traverse backward");
                    requestFocus(textField1);
                }
            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(HBoxBuilder.create().spacing(10).children(textField1, textField2, textField3).build());
        Scene scene = new Scene(root, 300, 150);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void requestFocus(final Node node) {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                node.requestFocus();
            }
        });
    }

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