按下箭头时键绑定没有响应

Key binding not responding when arrow pressed

您好,我正在 Java(mac)中开发应用程序。当用户按下箭头时,我想让它做点什么。

我的代码如下:

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);
}

}

它只是一个创建 JFrame 并在其中放入 StandartPanel 和带有按钮的 JToolBar 的程序。

StandartPanel的代码如下:

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");
        }
    });
}

}

for 循环并不重要,重要的是当按下 D 或 Down 时它会打印 "pressed"。

当我实际按下 D 时它打印 "pressed" 但是当我按下时它什么也不做。

在尝试了一些事情之后,我发现如果不是向 JToolBar 添加 JButton,而是添加 JLabel,它就可以工作(如果我不添加任何东西,它也可以工作)。

因此,将 JButton 添加到 JToolBar 会以某种方式停止使用向下按钮的键绑定。

关于它发生的原因以及如何解决的任何想法?

谢谢!

最简单的方法是将您的(JToolBar 和)JButton 设置为不可聚焦。 (请参阅 this,JToolBar 通常会注册 UP/DOWN/LEFT/RIGHT 以切换工具栏内按钮的焦点。)但是要小心!这将阻止 JToolbar 从 "hopping" 从一个项目到另一个项目。 (如果您想保留该功能,请查看 MadProgrammer 的回答)- 在您的代码中实现它看起来像这样:

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");
                }
            });
        }

    }

}

正在我的 Mac 上进行测试:

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_DOWN, 0, true), "forward");

哦,而且,而不是使用...

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

考虑使用...

f.setExtendedState(JFrame.MAXIMIZED_BOTH);

它不仅会给出一个模拟结果,还会考虑 hidden/shown 停靠并以更正确的方式表示 window 状态(即最大化和不只是 "filling" 地区)