4

我想创建要在其中配置热键快捷方式的表。

我有这个简单的表:

    public static final String Column1MapKey = "A";
    public static final String Column2MapKey = "B";

    private ObservableList<Map> generateDataInMap() {
        int max = 110;
        ObservableList<Map> allData = FXCollections.observableArrayList();
        for (int i = 1; i < max; i++) {
            Map<String, String> dataRow = new HashMap<>();

            String value1 = "A" + i;
            String value2 = "B" + i;

            dataRow.put(Column1MapKey, value1);
            dataRow.put(Column2MapKey, value2);

            allData.add(dataRow);
        }
        return allData;
    }

public TabPane hotKeysContent(){

        TableColumn<Map, String> firstDataColumn = new TableColumn<>("Actions");
        TableColumn<Map, String> secondDataColumn = new TableColumn<>("Shortcut");

        firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey));
        firstDataColumn.setMinWidth(230);
        secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey));
        secondDataColumn.setMinWidth(230);

        TableView table_view = new TableView<>(generateDataInMap());
        table_view.setPadding(new Insets(5, 5, 5, 5));

        table_view.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);  // Autoresize when window size is changed

        table_view.setEditable(true);
        table_view.getSelectionModel().setCellSelectionEnabled(true);
        table_view.getColumns().setAll(firstDataColumn, secondDataColumn);
        Callback<TableColumn<Map, String>, TableCell<Map, String>>
            cellFactoryForMap = new Callback<TableColumn<Map, String>,
                TableCell<Map, String>>() {
                    @Override
                    public TableCell call(TableColumn p) {
                        return new TextFieldTableCell(new StringConverter() {
                            @Override
                            public String toString(Object t) {
                                return t.toString();
                            }
                            @Override
                            public Object fromString(String string) {
                                return string;
                            }                                    
                        });
                    }
        };
        firstDataColumn.setCellFactory(cellFactoryForMap);
        secondDataColumn.setCellFactory(cellFactoryForMap);

        return null;
    }

当我单击第二列中的一行时,我希望获得我将按下的键组合,然后使用这些键来激活键盘快捷键。任何示例都会有所帮助。

带有命令的 PS 表:

public static final String Column1MapKey = "A";
    public static final String Column2MapKey = "B";

    private ObservableList<Map> generateDataInMap() {
        int max = 110;
        ObservableList<Map> allData = FXCollections.observableArrayList();
        for (int i = 1; i < max; i++) {
            Map<String, String> dataRow = new HashMap<>();

            String value1 = "A" + i;
            String value2 = "B" + i;

            dataRow.put(Column1MapKey, value1);
            dataRow.put(Column2MapKey, value2);

            allData.add(dataRow);
        }
        return allData;
    }

    public TabPane hotKeysContent(){

        TabPane tabPane = new TabPane();
        //tabPane.setStyle("-fx-font-size: 13pt;"); // Set size of the tab name

        Tab tabA = new Tab();
        Label tabALabel = new Label("Shortcuts");
        //tabALabel.setStyle("-fx-font-size: 12pt;"); // Set size of the tab name
        tabA.setGraphic(tabALabel);
        tabA.setClosable(false); // da se mahne opciqta da se zatvarq tab


        TableColumn<Map, String> firstDataColumn = new TableColumn<>("Actions");
        TableColumn<Map, String> secondDataColumn = new TableColumn<>("Shortcut");

        firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey));
        firstDataColumn.setMinWidth(230);
        secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey));
        secondDataColumn.setMinWidth(230);

        TableView table_view = new TableView<>(generateDataInMap());
        table_view.setPadding(new Insets(5, 5, 5, 5));

        table_view.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);  // Autoresize when window size is changed

        table_view.setEditable(true);
        table_view.getSelectionModel().setCellSelectionEnabled(true);
        table_view.getColumns().setAll(firstDataColumn, secondDataColumn);
        Callback<TableColumn<Map, String>, TableCell<Map, String>>
            cellFactoryForMap = new Callback<TableColumn<Map, String>,
                TableCell<Map, String>>() {
                    @Override
                    public TableCell call(TableColumn p) {
                        return new TextFieldTableCell(new StringConverter() {
                            @Override
                            public String toString(Object t) {
                                return t.toString();
                            }
                            @Override
                            public Object fromString(String string) {
                                return string;
                            }                                    
                        });
                    }
        };
        firstDataColumn.setCellFactory(cellFactoryForMap);
        secondDataColumn.setCellFactory(cellFactoryForMap);

        tabA.setContent(table_view);                
        tabPane.getTabs().add(tabA);       

        return tabPane;
    }
4

3 回答 3

8

下面是一个 SSCCE,虽然没有 tableView 没有列或单元格。然而逻辑是相似的。检查它以寻找线索并根据您的需要编写自己的代码:

public class ShortCutDemo extends Application {

    private KeyEvent shortcutKeyEvent;
    private EventHandler selectedEventHandler;
    private List<EventHandler> eventHandlers;
    private HBox root;

    @Override
    public void start(Stage primaryStage) {

        root = new HBox(10);
        root.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                // Do not filter for TextFields
                if (event.getTarget() instanceof TextField) {
                    return;
                }
                if (isKeyEventsAreEqual(event, shortcutKeyEvent)) {
                    // then apply shortcut event
                    selectedEventHandler.handle(null);
                    event.consume();
                }
            }
        });

        eventHandlers = new ArrayList<EventHandler>();
        eventHandlers.add(new EventHandler() {
            @Override
            public void handle(Event event) {
                root.setStyle("-fx-background-color: lightgray");
            }
        });

        eventHandlers.add(new EventHandler() {
            @Override
            public void handle(Event event) {
                root.setSpacing(50);
            }
        });

        ChoiceBox cb = new ChoiceBox();
        cb.getItems().addAll("HBox background = gray", "HBox spacing = 50");
        cb.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                selectedEventHandler = eventHandlers.get(newValue.intValue());
            }
        });
        cb.getSelectionModel().selectFirst(); // default value

        final TextField textField = new TextField();
        textField.setEditable(false);

        textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                if (event.getCode() == KeyCode.TAB) {
//                    Platform.runLater(new Runnable() {
//                        @Override
//                        public void run() {
//                            root.requestFocus();
//                        }
//                    });
                } else {
                    // Clear the previous text
                    textField.setText("");
                    // Process only desired key types
                    if (event.getCode().isLetterKey()
                            || event.getCode().isDigitKey()
                            || event.getCode().isFunctionKey()) {
                        String shortcut = event.getCode().getName();
                        if (event.isAltDown()) {
                            shortcut = "Alt + " + shortcut;
                        }
                        if (event.isControlDown()) {
                            shortcut = "Ctrl + " + shortcut;
                        }
                        if (event.isShiftDown()) {
                            shortcut = "Shift + " + shortcut;
                        }
                        textField.setText(shortcut);
                        shortcutKeyEvent = event;
                    } else {
                        shortcutKeyEvent = null;
                    }
                }
            }
        });

        Button button = new Button("Reset");
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                textField.setText("");
                root.setSpacing(10);
                root.setStyle("-fx-background-color: white");
                shortcutKeyEvent = null;
            }
        });

        root.getChildren().addAll(new Label("Define a shortcut for "), cb, textField, button);
        Scene scene = new Scene(root, 900, 150);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private boolean isKeyEventsAreEqual(KeyEvent event1, KeyEvent event2) {
        return event1 != null
                && event2 != null
                && event1.getCode() == event2.getCode()
                && event1.isAltDown() == event2.isAltDown()
                && event1.isControlDown() == event2.isControlDown()
                && event1.isShiftDown() == event2.isShiftDown();
    }

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

这个怎么运作?
1) 从选择框中选择一个动作(事件)类型。
2) 聚焦到 Textfield 并键入所需的快捷方式,例如Alt+ 。 3) 按以从 TextField 中聚焦。 4) 再次按下快捷键(在本例中为+ )以查看正在发生的事件。 5) 按“复位”按钮,确定复位状态。F1
Tab
AltF1

进一步的改进应该是定义一个模型类,它具有快捷键、Ctrl、Alt 和 Shift 的布尔值、用于处理的事件处理程序和适当的重写equals(...)方法。

于 2013-09-23T13:34:24.937 回答
1

这应该让你开始。为简单起见,我只处理了 ctrl 和 alt 元键以及一列,但如何继续应该很明显。我的方法是使用带有自定义 onKeyPressed 侦听器的TextFieldTableCell,该侦听器侦听快捷键并将它们转换为KeyCharacterCombination

请注意,此示例不是非常完整或稳健。例如,未正确处理单个字符。标准快捷键(Ctrl-C、Ctrl-V 等)不会被覆盖。您可能必须实现自己的 TableCell 类,以便完全控制键入的文本。

public class KeyCombinationTableExample extends Application {

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

    @Override
    public void start(Stage stage) throws Exception {
        final ObservableList<KeyCharacterCombination> items = FXCollections.observableArrayList();
        for (int i = 0; i < 110; i++) {
            items.add(null);
        }
        TableView<KeyCharacterCombination> table = new TableView<>(items);
        table.setEditable(true);
        final TableColumn<KeyCharacterCombination, KeyCharacterCombination> column = new TableColumn<>();
        column.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<KeyCharacterCombination, KeyCharacterCombination>, ObservableValue<KeyCharacterCombination>>() {
                                       @Override
                                       public ObservableValue<KeyCharacterCombination> call(TableColumn.CellDataFeatures<KeyCharacterCombination, KeyCharacterCombination> cellDataFeatures) {
                return new ReadOnlyObjectWrapper<>(cellDataFeatures.getValue());
        }
        });
        column.setCellFactory(new Callback<TableColumn<KeyCharacterCombination, KeyCharacterCombination>, TableCell<KeyCharacterCombination, KeyCharacterCombination>>() {
                                  @Override
                                  public TableCell<KeyCharacterCombination, KeyCharacterCombination> call(TableColumn<KeyCharacterCombination, KeyCharacterCombination> tableColumn) {
                final TableCell<KeyCharacterCombination, KeyCharacterCombination> cell = new TextFieldTableCell<KeyCharacterCombination, KeyCharacterCombination>() {
                    @Override
                    public void updateItem(KeyCharacterCombination keyCharacterCombination, boolean b) {
                        super.updateItem(keyCharacterCombination, b);
                        if (this.getItem() == null || b) {
                            setText(null);
                        } else {
                            StringBuilder sb = new StringBuilder();
                            if (keyCharacterCombination.getControl() == KeyCombination.ModifierValue.DOWN) {
                                sb.append("Ctrl + ");
                            }
                            if (keyCharacterCombination.getAlt() == KeyCombination.ModifierValue.DOWN) {
                                sb.append("Alt + ");
                            }
                            sb.append(keyCharacterCombination.getCharacter());
                            setText(sb.toString());
                        }
                    }
                };
                cell.setOnKeyPressed(new EventHandler<KeyEvent>() {
                    Set<KeyCombination.Modifier> keys = new HashSet<>();

                    @Override
                    public void handle(KeyEvent keyEvent) {
                        if (keyEvent.getCode() == KeyCode.CONTROL) {
                            keys.add(KeyCombination.CONTROL_DOWN);
                        } else if (keyEvent.getCode() == KeyCode.ALT) {
                            keys.add(KeyCombination.ALT_DOWN);
                        } else if (keyEvent.getCode().isLetterKey()) {
                            items.set(cell.getIndex(), new KeyCharacterCombination(keyEvent.getCode().getName(),
                                    keys.toArray(new KeyCombination.Modifier[keys.size()])));
                            keys.clear();
                        }
                    }
                });
                return cell;
        }
        });
        table.getColumns().add(column);
        stage.setScene(new Scene(table));
        stage.show();
    }
}
于 2013-09-23T23:32:51.747 回答
0
public class KeyboardExample extends Application{
 @Override
    public void start(final Stage stage) {
        final Keyboard keyboard = new Keyboard(new Key(KeyCode.A),
                                               new Key(KeyCode.S),
                                               new Key(KeyCode.D),
                                               new Key(KeyCode.F));

        final Scene scene = new Scene(new Group(keyboard.createNode()));
        stage.setScene(scene);
        stage.setTitle("Keyboard Example");
        stage.show();
    }

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

    private static final class Key {
        private final KeyCode keyCode;
        private final BooleanProperty pressedProperty;

        public Key(final KeyCode keyCode) {
            this.keyCode = keyCode;
            this.pressedProperty = new SimpleBooleanProperty(this, "pressed");
        }

        public KeyCode getKeyCode() {
            return keyCode;
        }

        public boolean isPressed() {
            return pressedProperty.get();
        }

        public void setPressed(final boolean value) {
            pressedProperty.set(value);
        }

        public Node createNode() {
            final StackPane keyNode = new StackPane();
            keyNode.setFocusTraversable(true);
            installEventHandler(keyNode);

            final Rectangle keyBackground = new Rectangle(50, 50);
            keyBackground.fillProperty().bind(
                    Bindings.when(pressedProperty)
                            .then(Color.RED)
                            .otherwise(Bindings.when(keyNode.focusedProperty())
                                               .then(Color.WHITE)
                                               .otherwise(Color.WHITE)));
            keyBackground.setStroke(Color.BLACK);
            keyBackground.setStrokeWidth(2);
            keyBackground.setArcWidth(12);
            keyBackground.setArcHeight(12);

            final Text keyLabel = new Text(keyCode.getName());
            keyLabel.setFont(Font.font("Arial", FontWeight.BOLD, 20));

            keyNode.getChildren().addAll(keyBackground, keyLabel);

            return keyNode;
        }

        private void installEventHandler(final Node keyNode) {
            // handler for enter key press / release events, other keys are
            // handled by the parent (keyboard) node handler
            final EventHandler<KeyEvent> keyEventHandler =
                    new EventHandler<KeyEvent>() {
                        public void handle(final KeyEvent keyEvent) {
                            if (keyEvent.getCode() == KeyCode.ENTER) {
                                setPressed(keyEvent.getEventType()
                                               == KeyEvent.KEY_PRESSED);

                                keyEvent.consume();
                            }
                        }
                    };

            keyNode.setOnKeyPressed(keyEventHandler);
            keyNode.setOnKeyReleased(keyEventHandler);
        }
    }

    private static final class Keyboard {
        private final Key[] keys;

        public Keyboard(final Key... keys) {
            this.keys = keys.clone();
        }

        public Node createNode() {
            final HBox keyboardNode = new HBox(6);
            keyboardNode.setPadding(new Insets(6));

            final List<Node> keyboardNodeChildren = keyboardNode.getChildren();
            for (final Key key: keys) {
                keyboardNodeChildren.add(key.createNode());
            }

            installEventHandler(keyboardNode);
            return keyboardNode;
        }

        private void installEventHandler(final Parent keyboardNode) {
            // handler for key pressed / released events not handled by
            // key nodes
            final EventHandler<KeyEvent> keyEventHandler =
                    new EventHandler<KeyEvent>() {
                        public void handle(final KeyEvent keyEvent) {
                            final Key key = lookupKey(keyEvent.getCode());
                            if (key != null) {
                                key.setPressed(keyEvent.getEventType()
                                                   == KeyEvent.KEY_PRESSED);

                                keyEvent.consume();
                            }
                        }
                    };

            keyboardNode.setOnKeyPressed(keyEventHandler);
            keyboardNode.setOnKeyReleased(keyEventHandler);

            keyboardNode.addEventHandler(KeyEvent.KEY_PRESSED,
                                         new EventHandler<KeyEvent>() {
                                             public void handle(
                                                     final KeyEvent keyEvent) {
                                                 handleFocusTraversal(
                                                         keyboardNode,
                                                         keyEvent);
                                             }
                                         });
        }

        private Key lookupKey(final KeyCode keyCode) {
            for (final Key key: keys) {
                if (key.getKeyCode() == keyCode) {
                    return key;
                }
            }
            return null;
        }

        private static void handleFocusTraversal(final Parent traversalGroup,
                                                 final KeyEvent keyEvent) {
            final Node nextFocusedNode;
            switch (keyEvent.getCode()) {
                case LEFT:
                    nextFocusedNode =
                            getPreviousNode(traversalGroup,
                                            (Node) keyEvent.getTarget());
                    keyEvent.consume();
                    break;

                case RIGHT:
                    nextFocusedNode =
                            getNextNode(traversalGroup,
                                        (Node) keyEvent.getTarget());
                    keyEvent.consume();
                    break;

                default:
                    return;
            }

            if (nextFocusedNode != null) {
                nextFocusedNode.requestFocus();
            }
        }

        private static Node getNextNode(final Parent parent,
                                        final Node node) {
            final Iterator<Node> childIterator =
                    parent.getChildrenUnmodifiable().iterator();

            while (childIterator.hasNext()) {
                if (childIterator.next() == node) {
                    return childIterator.hasNext() ? childIterator.next()
                                                   : null;
                }
            }

            return null;
        }

        private static Node getPreviousNode(final Parent parent,
                                            final Node node) {
            final Iterator<Node> childIterator =
                    parent.getChildrenUnmodifiable().iterator();
            Node lastNode = null;

            while (childIterator.hasNext()) {
                final Node currentNode = childIterator.next();
                if (currentNode == node) {
                    return lastNode;
                }

                lastNode = currentNode;
            }

            return null;
        }
    }

}

于 2014-08-20T05:12:16.557 回答