1

Hi there Im developing an application in Java (in a mac). When the user press the arrow down I wanted it to do something.

My code is the following:

public class Main {

static JScrollPane scrollPane;

public static void main(String[] args) {


    JFrame f = new JFrame();
    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
    f.setBounds(0, 0, dim.width, dim.height);

    StandartPanel p = new StandartPanel();

    f.add(p);

    JToolBar tb = new JToolBar();

    tb.add(new JButton("button"));

    f.add(tb);
    f.setVisible(true);
}

}

Its simply a program that creates a JFrame and puts in it a StandartPanel and a JToolBar which has a button.

The code of the StandartPanel is the following:

public class StandartPanel extends JPanel {


public StandartPanel () {

    for( int i = 0; i < 10; i++)
        this.add(new JLabel("Jlabel number: " + i));

    this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "forward");
    this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "forward");
    this.getActionMap().put("forward", new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("pressed");
        }
    });
}

}

The for loop is not important, the important is that it prints "pressed" when D or Down is pressed.

When I actually press D it prints "pressed" but when I click down it does nothing.

After trying some things I have discover that if instead of adding a JButton to the JToolBar I add a JLabel it works (if I don't add anything it also works).

So adding a JButton to the JToolBar somehow stops the key binding working with the down button.

Any ideas of why it is happening and how it could be fixed??

Thank you!

Antonio
  • 409
  • 5
  • 12
  • Hava a look at [this](http://stackoverflow.com/a/17049479/4857909) – Lukas Rotter Sep 04 '15 at 11:46
  • Have a look at http://stackoverflow.com/questions/9973190/keyadapter-listener-works-in-windows-not-on-mac – Georgi Penev Sep 04 '15 at 11:59
  • @GeorgiPenev It also doesn't work for me (Windows). Also he already uses KeyBindings, not a KeyListener. – Lukas Rotter Sep 04 '15 at 12:13
  • possible duplicate of [KeyBinding not working with arrow](http://stackoverflow.com/questions/32377384/keybinding-not-working-with-arrow) – RealSkeptic Sep 04 '15 at 12:14
  • Please do not post the same question twice. – RealSkeptic Sep 04 '15 at 12:14
  • You were asked in your last question to post a `SSCCE`. This is NOT a SSCCE. As I suggested we needed more information. Post a proper SCCEE. Notice how you can copy/paste/execute the accepted answer. How do you expect us to do the same with the code you posted??? – camickr Sep 04 '15 at 14:22

2 Answers2

3

Testing it on my Mac:

this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "forward");

did NOT work, but, for some reason I can't explain, using...

this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "forward");

does

Oh, and, instead of using...

Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
f.setBounds(0, 0, dim.width, dim.height);

Consider using...

f.setExtendedState(JFrame.MAXIMIZED_BOTH);

It will no only give a simular result, it will take into account things like hidden/shown docks and represent the window state in manner which is more correct to it's state (ie, maximised and not just "filling" the area)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • (+1) My **guess** why your solution works is because it only triggers the event when key released, the JToolBar probably on key pressed. (and blocks the other actions) - But I'm sure my "theory" can be easily disproven :P – Lukas Rotter Sep 04 '15 at 13:02
  • @LuxxMiner I thought that to, but `JToolBar` has a binding for `KeyEvent.VK_KP_DOWN` as well, and I can use that just fine, without modification, there seems to be something more going on with the `VK_DOWN` key that I'm not seeing. If I add a focusable component to the OP's `StandartPanel` and give it focus, it all works fine ... I'm stumped at this stage, cause `WHEN_IN_FOCUSED_WINDOW` shouldn't care who else might be responding to the key event (from my experience up to now) – MadProgrammer Sep 04 '15 at 13:06
  • @MadProgrammer Really? `this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( KeyStroke.getKeyStroke(KeyEvent.VK_KP_DOWN, 0), "forward");` doesn't work for me... It becomes more and more strange :D – Lukas Rotter Sep 04 '15 at 13:19
2

The easiest way is to set your (JToolBar and) JButton unfocusable. (see this, a JToolBar normally registeres UP/DOWN/LEFT/RIGHT for switching the focus of the buttons inside the toolbar.) But be careful! This will block the JToolbar from "hopping" from one item to the other. (If you want to keep that feature, take a look at MadProgrammer's answer) - Implemented in your code it would look like this:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;

public class Main {

    static JScrollPane scrollPane;

    public static void main(String[] args) {

        JFrame f = new JFrame();
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        f.setBounds(0, 0, dim.width, dim.height);

        StandartPanel p = new StandartPanel();

        f.add(p);

        JToolBar tb = new JToolBar();

        JButton button = new JButton("Button");
        button.setFocusable(false);

        tb.add(button);
        //tb.setFocusable(false);

        f.add(tb, BorderLayout.NORTH);
        f.setVisible(true);
    }

    static class StandartPanel extends JPanel {

        public StandartPanel() {

            for (int i = 0; i < 10; i++) {
                this.add(new JLabel("Jlabel number: " + i));
            }

            this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                    KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "forward");
            this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                    KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "forward");
            this.getActionMap().put("forward", new AbstractAction() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("pressed");
                }
            });
        }

    }

}
Community
  • 1
  • 1
Lukas Rotter
  • 4,158
  • 1
  • 15
  • 35
  • Using `WHEN_IN_FOCUSED_WINDOW` means that so long as the component is within the currently focused window, the key binding should trigger. Given the the OP can get it to work for the [D] key but down the [Down Arrow], suggests that their is something else at play – MadProgrammer Sep 04 '15 at 12:51
  • @MadProgrammer A JToolBar automatically registers actions of UP/DOWN/LEFT/RIGHT (hopping from one item to the other) - Setting all buttons unfocusable will prevent that. (that's why it works with JLabels) – Lukas Rotter Sep 04 '15 at 12:56
  • It shouldn't (but does) make a difference, but is changing the user expectations of the tool-bar worth getting the key binding to work. Interesting things to be thought about ;) – MadProgrammer Sep 04 '15 at 12:58
  • Oh, could you also add that explanation to you answer, for silly old idiots like me ;) – MadProgrammer Sep 04 '15 at 13:00
  • Adding to the weird ness, if I use `KeyEvent.VK_KP_DOWN`, which is also used by the `JToolBar`, it works just fine, there seems to be something wrong with the "non-key pad" arrow keys...spooky :P – MadProgrammer Sep 04 '15 at 13:04
  • It worked doing this! Thanks LuxxMiner! However in my real program there where more things and in order to work I had to set the focusable to false for every button in order to work. – Antonio Sep 04 '15 at 13:09
  • @Chris That's the main problem with my answer - If you want to keep that feature (switching focus of items), try MadProgrammer's solution. – Lukas Rotter Sep 04 '15 at 13:10