This is in the constructor of a JPanel but it does not print anything when I press "h". If more code is needed, I can provide it. Thank you!
String hide = "hide";
this.getInputMap().put(KeyStroke.getKeyStroke('h'), hide);
this.getActionMap().put(hide, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("HIDDEN");
if (isHidden){
slide.setVisible(true);
}else{
slide.setVisible(false);
}
}
});
this.getInputMap()....
You are trying to add the bindings to the default InputMap, which is the InputMap when the component has focus. By default a JPanel does not have focus.
You should try using one of the other InputMaps by using the getInputMap(int) method. Or you will need to make the panel focusable and give it focus.
Read the Swing tutorial on How to Use Key Bindings for more information on the proper variables to use to specify the desired InputMap.
Related
I have a JFrame called gameFrame and I added a Jpanel called introPanel to it, gameFrame.add(introPanel) and I wanted to listen to the JPanel with a keylistener so I added one. When the user presses Enter, I removed the JPanel from the gameFrame and added the MainMenu theoretically, however the program doesnt listen to my keys. So i looked online and through SO and found out that I had to make the panel focusable so I did:
public IntroMenuStart() {
this.addKeyListener(this);
this.setFocusable(true);
this.requestFocusInWindow();
}
However this did not work either. What else can I do to fix this?
Each Panel is a seperate class and they all get removed from gameframe and the next panel is added.
I would prefer to do this with keylistener.
EDIT
I fixed it by including this in my code for anyone wanting to know but I'm going to be changing my code to Keybindings like the 2 answers suggsted.
public void addNotify() {
super.addNotify();
requestFocus();
}
i want to listne to the panel with a key listener so i add one. When
the user presses Enter, i remove to JPanel form the gameFrame and add
MainMenu, theoretically, however the program doesnt listen to my keys
If you search in deep in SO , you'll see that you have to use KeyBindings
KeyListener has 2 greate issues, you listen to all keys and you have to have focus.
Instead KeyBinding you bind for a key and you don't have to be in focus.
Simple Example:
AbstractAction escapeAction = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
//code here example
((JComponent)e.getSource()).setVisible(Boolean.FALSE);
}};
String key = "ESCAPE";
KeyStroke keyStroke = KeyStroke.getKeyStroke(key);
component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, key);
component.getActionMap().put(key, escapeAction);
You can use these JComponent constants
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
WHEN_FOCUSED
WHEN_IN_FOCUSED_WINDOW
I believe that JPanel is not focuseable. Instead, use the key bindings.
See How to Use Key Bindings.
I have some difficulties with setting a shortcut to my dynamically added buttons. Buttons are on dynamically added panel. I want to add keyboard shortcuts to these buttons, like so:
ctrl+1 -> button1
ctrl+2 -> button2
etc.
Buttons are added by an algorithm, so I don't know how many of them there will be(min 0, max 5). I would like to call these buttons with Global (working in whole panel) keyboard shortcuts. I am wondering how to achieve this, when the text on my button is made dynamically like this:
getNewAmountQueryButton(label)
which makes this:
private JButton getNewAmountQueryButton(final Decimal label) {
JButton temp = new JButton(label.toString());
...
I tried adding keylistener but it works only when I have a focus on a button:
button.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(final KeyEvent e) {
#Override
public void run() {
if ((e.getKeyCode() == getKeyCode()) && ((e.getModifiers() & InputEvent.CTRL_MASK) != 0)) {
model.setAmount(model.getAmount().add(label));
field().selectAll();
refreshDisplay();
}
}
});
});
Do you know how can I do this? I wanted to add listener to top-level panel, but as I use model.setAmount(model.getAmount().add(label));to refresh some textField it is impossible due to lack of this label parameter.
Any idea?
Thanks in advance!
It is recommend that you use Key Bindings.
Bascially, they don't suffer from the same focus issues as KeyListeners
Use Action to encapsulate each button's behvior. You can specify the desired MNEMONIC_KEY, as shown here, and you can add a binding to the ACCELERATOR_KEY, as shown here.
I have a JFrame with multiple panels that accumulates in a fairly complex Swing UI. I want to add Keyboard support so that regardless of component focus a certain Key press, for example the [ENTER] key, causes a listener to react.
I tried adding a KeyListener to the JFrame but that doesn't work if another JComponent is selected which changes focus.
Is there a proper way to do this?
Registering a KeyEventDispatcher with the KeyboardFocusManager allows you to see all key events before they are sent to the focused component. You can even modify the event or prevent it from beeing delivered to the focused component:
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
new KeyEventDispatcher() {
public boolean dispatchKeyEvent(KeyEvent e) {
//Get the char which was pressed from the KeyEvent:
e.getKeyChar();
//Return 'true' if you want to discard the event.
return false;
}
});
If you just want to get the key inputs for one window / component or just for specific keys, you can use KeyBindings as kleopatra suggested. As an example on how to register to the keyboard event on Enter pressed (You may use any VK_ provided by KeyEvent, for modifiers [alt, ctrl, etc.] see InputEvent) see:
JFrame frame = new JFrame(); //e.g.
JPanel content = (JPanel)frame.getContentPane();
content.getInputMap().put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ENTER,0),"enterDown");
content.getActionMap().put("enterDown",new AbstractAction() {
private static final long serialVersionUID = 1l;
#Override public void actionPerformed(ActionEvent e) {
//This action is called, as the Enter-key was pressed.
}
});
The way I do it is to make the JFrame focusable and append the listener to it. Then, iterate through all the JFrame children and make everything else not focusable.
Of course this only works if you don't have text boxes or similar as they will become non editable.
I am writing a simple java snake-like game, and I ran into a problem even before I actually got to making the game. I can't seem to get input from the keyboard for some reason. My current code is:
public class GameWindow extends JFrame{
private SnakeCanvas snakeCanvas;
public GameWindow(StartWindow sw) {
getContentPane().addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
JOptionPane.showMessageDialog(null, "Key Pressed!");
}
});
getContentPane().setBackground(Color.BLACK);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setUndecorated(true);
this.setVisible(true);
getContentPane().setLayout(null);
snakeCanvas = new SnakeCanvas();
snakeCanvas.setBounds(78, 72, 290, 195);
getContentPane().add(snakeCanvas);
snakeCanvas.setVisible(true);
snakeCanvas.repaint();
}
}
(a SnakeCanvas extends JPanel and has no other components on it)
I've tried also adding a key listener to the snakeCanvas and still no effect..
I've also tried to play with the focusable and the focus Traversal stuff but that also didn't do anything...
Can anyone please explain to me what I'm doing wrong?
Make sure you have set the components you want to receive keyboard events is focusable (setFocusable) & has focus (requestFocus)
KeyListener isn't proper listener for Swing JComponents, required focus in the window
you have to setFocusable for container
right and correct way is usage of KeyBindings, for example
I'm trying to use an editable JComboBox such that upon a user typing into the editor, possible results are displayed in the list part of the combo box.
Unfortunately, I've found that upon using either addItem(item) or getModel().addItem(item), the input typed by the user is overwritten by the first value I added. I've considered storing the editor value, adding items, and then using setSelectedItem() to fix this, but I wan't to preserve the state of any selected text/ caret position, and believe this should be something more trivial, but can't for the life of me figure it out.
JComboBox box = new JComboBox();
box.setModel(new MutableComboBoxModel());
box.setEditable(true);
box.getEditor().getEditorComponent().addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
// Actual results are retrieved from server via HTTP
box.addItem("Demo");
// Here, the editor window the user was typing in is replaced with the value "Demo".. how to fix this?
}
});
use AutoComplete JComboBox / JTextField,
for listening in JTextComponent is there DocumentListener,
never use KeyListener for Swing JComponents, this listener is designated for AWT Components, for Swing JComponents is there KeyBindings
You need to implement your own MutableComboBoxModel since DefaultComboBoxModel is responsible for the "add item then auto select it" behavior.