I want to create table in which I want to configure hot key shortcuts.
I have this simple table:
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;
}
I want when I click on a row into the second column to get the combination of keys which I will press and later to use these keys to activate keyboard shortcuts. Any example will be helpful.
P.S Table with the commands:
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;
}
Below is a SSCCE, though there is no tableView no column or cell. However the logic is similar. Examine it for clues and write your own code according to your needs:
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);
}
}
How it works?
1) Select an action (event) type from choicebox.
2) Focus to Textfield and type the desired shortcut, Alt+F1 for example.
3) Press Tab to focus out from TextField.
4) Press the shortcut (Alt+F1 in this case) again to see the event in action.
5) Press "Reset" button to reset the state surely.
The further improvement should be defining a model class, that have ShortCut key, booleans for Ctrl, Alt and Shift, eventhandler to process and appropriately overriden equals(...)
method.
Here's something that should get you started. For simplicity I only handled ctrl and alt meta keys and only one column, but it should be obvious how to continue. My approach was to use a TextFieldTableCell with a custom onKeyPressed listener that listens for key shortcuts and translates them into KeyCharacterCombinations.
Note that this example is not very complete or robust. For example, single characters are not handled properly. Standard shortcuts (Ctrl-C, Ctrl-V, etc) are not overridden. You will probably have to implement your own TableCell class so you can fully control what text is typed.
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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With