JDK-8087451 : [TextArea, TextField] TextField and TextArea don't consume Accelerators
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: 7u65,8u20
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2014-08-13
  • Updated: 2015-11-13
  • Resolved: 2015-09-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Fixed
Related Reports
Relates :  
Relates :  
Description
Adding an accelerator for a typeable character such as SHIFT+1 should only activate the Accelerator if the character typed is not consumed by another control.  However, TextField will get the typed character AND the accelerator attached to the Scene will fire.
Comments
Filed JDK-8142981 for the Alt-based accelerator issue.
13-11-2015

The ALT situation is difficult to resolve. - Accelerators use KEY_PRESSED events, while the text input controls use KEY_TYPED. - KEY_PRESSED events arrive first and don't contain the decoded character, so we can't tell if we will use and consume the expected KEY_TYPED event. - Some ALT accelerators need to bubble up, such as ALT-up/down for ComboBox. We could hard code for these ALT KEY_PRESSED events that we know of and consume the rest, but I'm worried that it will be hard to maintain and will make it hard to add functionality later on. I will file a new issue for this and keep this one resolved.
18-09-2015

Consuming KEY_PRESSED just with & without SHIFT is not enough. For example Alt+G types a copyright symbol on Mac. When I add an accelerator for ALT+G to the test app above, it also does both the accelerator and the typing of a copyright symbol.
18-09-2015

Now consuming all KEY_PRESSED events with or without shift. Changeset: http://hg.openjdk.java.net/openjfx/9-dev/rt/rev/60da505acaea
18-09-2015

Thanks for shortcut hint. I have multiple accelerators assigned to the number keys with different modifiers though - shortcut would be one of them. Though I was used to Swing so I had my own field defined as either CTRL or META. The problem with using SHORTCUT though is that I then don't know what other modifier I can combine with it. For an example on my Mac I see in the Edit menu that CTRL+COMMAND+SPACE is used to access "Special Characters..." - a popup allowing me to select emoticons, symbols etc. So on a Mac I can have both CTRL+X and CTRL+META+X as valid accelerators. If I coded that as CTRL+X and CTRL+SHORTCUT+X it would break on Windows. Sometimes ya just gotta be aware of those platform differences :-)
13-08-2014

I agree, it seems wrong. BTW, you should use the shortcut mechanism to help choose accelerators (ie. KeyCombination.keyCombination("shortcut+Y")). This will help avoid the bug and make the accelerators that you choose portable.
13-08-2014

@Steve Given the behavior for CTRL+C and CTRL+V, I don't think this is a documentation issue as you suggest. Add the following to my test case and see for yourself: map.put(new KeyCodeCombination(KeyCode.C, KeyCombination.CONTROL_DOWN), ()->{ label.setText("CTRL+C - did this happen?");}); map.put(new KeyCodeCombination(KeyCode.V, KeyCombination.CONTROL_DOWN), ()->{ label.setText("CTRL+V - how about a paste?");}); Try with the TextField or TextArea focused, then again with the Button focused.
13-08-2014

> Doesn't matter if I use scene.getAccelerators().put(....) or just set the accelerator on a MenuItem, the result is the same. Ok, this seems wrong. Normally, an accelerator needs to consume the key to avoid an action running twice (once for the accelerator and once when the key goes to the control).
13-08-2014

Doesn't matter if I use scene.getAccelerators().put(....) or just set the accelerator on a MenuItem, the result is the same. Given that on different keyboard layouts and operating systems you may not know what keypresses result in typed characters or not, it is impossible to easily select KeyCombinations that won't have problems. E.g. Alt+LETTER is often used to type accented characters Notice that accelerators for CTRL+c and CTRL+V do NOT have this problem, The work as copy/paste when the TextField has focus, but they work as Accelerators when it does not.
13-08-2014

I can also confirm that SHIFT+A is not consumed. It is likely that this is operating as it should and the Javadoc needs to be changed.
13-08-2014

package acceleratortest; import javafx.application.Application; import javafx.collections.ObservableMap; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCombination; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class AcceleratorTest extends Application { Label label; @Override public void start(Stage primaryStage) { label = new Label("Message goes here"); VBox root = new VBox(8); root.setPadding(new Insets(16)); root.getChildren().addAll( new Label("Type any of !@#$%^&*() in the text field below.\n" + "Typing in the text field should not activate the Accelerator\n" + "but it does."), new TextField(), new TextArea(), new Button("Just another focusable control"), label); Scene scene = new Scene(root); ObservableMap<KeyCombination, Runnable> map = scene.getAccelerators(); map.put(new KeyCodeCombination(KeyCode.DIGIT1, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 1");}); map.put(new KeyCodeCombination(KeyCode.DIGIT2, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 2");}); map.put(new KeyCodeCombination(KeyCode.DIGIT3, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 3");}); map.put(new KeyCodeCombination(KeyCode.DIGIT4, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 4");}); map.put(new KeyCodeCombination(KeyCode.DIGIT5, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 5");}); map.put(new KeyCodeCombination(KeyCode.DIGIT6, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 6");}); map.put(new KeyCodeCombination(KeyCode.DIGIT7, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 7");}); map.put(new KeyCodeCombination(KeyCode.DIGIT8, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 8");}); map.put(new KeyCodeCombination(KeyCode.DIGIT9, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 9");}); map.put(new KeyCodeCombination(KeyCode.DIGIT0, KeyCombination.SHIFT_DOWN), ()->{ label.setText("SHIFT + 0");}); primaryStage.setTitle("TextField doesn't consume characters properly?"); primaryStage.setScene(scene); primaryStage.show(); } /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } }
13-08-2014