按下其他键后,JButton键侦听器不会触发 [英] JButton Key listener not firing after other key is pressed

查看:205
本文介绍了按下其他键后,JButton键侦听器不会触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Java创建一个虚拟钢琴。到目前为止,我有两个按键的动作监听器,它们大部分工作,而不是一个接一个。例如,我在键盘上点击 q 并按下 c 键并播放ac,这就是它的假设去做。但是我想通过在键盘上点击 w 来点击钢琴上的d键,如果我已经击中了<$ c $,它就不会这样做c> q 键。

I am creating a virtual piano in Java. So far I have action listeners for two of the keys which work for the most part, just not after one another. For example, I hit q on the keyboard and it presses the c key and plays a c, which is what it's supposed to do. But then I want to hit the d key on the piano by hitting w on the keyboard, and it won't do it if I've already hit the q key.

// c key
        JButton btnC3 = new JButton("");
        btnC3.addKeyListener(new KeyAdapter() 
        {
            @Override
            public void keyPressed(KeyEvent e) 
            {
                if (e.getKeyCode() == KeyEvent.VK_Q)
                {
                    btnC3.doClick();
                }
            }
        });
        btnC3.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
                // play c
                try 
                {
                    keys.playNote(Notes.c3.getValue());
                } 
                catch (InterruptedException e1) 
                {
                    e1.printStackTrace();
                }
                catch (InvalidMidiDataException e2)
                {
                    e2.printStackTrace();
                }
            }
        });
// d key
JButton btnD3 = new JButton("");
        btnD3.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) 
            {
                if (e.getKeyCode() == KeyEvent.VK_W)
                {
                    btnD3.doClick();
                }
            }
        });
        btnD3.addActionListener(new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
                // play d
                try 
                {
                    keys.playNote(Notes.d3.getValue());
                } 
                catch (InterruptedException e1) 
                {
                    e1.printStackTrace();
                }
                catch (InvalidMidiDataException e2)
                {
                    e2.printStackTrace();
                }
            }
        });
        btnD3.setBackground(Color.WHITE);
        btnD3.setBounds(wKeyWidth*1, 0, wKeyWidth, wKeyHeight);
        frame.getContentPane().add(btnD3);


推荐答案

问题与关键板焦点有关, KeyListener 只会在侦听器注册到IS可聚焦和HAS焦点的组件时生成事件。

The problem is related to key board focus, a KeyListener will only generate events when the component the listener is registered to IS focusable and HAS focus.

显然,当a按钮被点击它获得焦点,这意味着其他任何组件都无法响应。

Obviously, when a button is "clicked" it gains focus, meaning that none of the other components can responds.

基本答案是,使用的是使用密钥绑定API

The basic answer is, use is the Use Key Bindings API.

那里您可以做出多种选择,您可以使用当前容器来注册密钥绑定,例如......

There are a number of choices you can make, you can use the current container to register the key bindings against, for example...

InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();

JButton btnC3 = new JButton("");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "c3");
am.put("c3", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        btnC3.doClick();
    }
});
btnC3.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // play c
        try {
            keys.playNote(Notes.c3.getValue());
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        } catch (InvalidMidiDataException e2) {
            e2.printStackTrace();
        }
    }
});

JButton btnD3 = new JButton("");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "d3");
am.put("d3", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        btnD3.doClick();
    }
});

或者您可以在各个组件中注册它们。选择主要取决于您希望解决方案的可重用性。

or you can register them against in the individual components. The choice will mostly come down to how reusable you want the solution to be.

例如,您可以创建一个 Action 可以应用于 JButton 和键绑定,这意味着您无需以编程方式单击该按钮。

For example, you could create a Action which can be applied to both the JButton and key binding which means you don't need to programmatically click the button.

例如......

public class NoteAction extends AbstractAction {
    private Note note;
    private Keys keys;

    public NoteAction(Note note, Keys keys) {
        this.note = note;
        this.keys = keys;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        keys.playNote(note.getValue());
    }

}

(我不是我有你的代码,所以我只是制作一些类名。

然后你可以简单地使用......

Then you could simply use...

NoteAction noteAction = new NoteAction(Notes.d3, keys);
JButton btnC3 = new JButton(noteAction);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), "c3");
am.put("c3", noteAction);

进行设置。

参见如何使用操作了解更多详情

这篇关于按下其他键后,JButton键侦听器不会触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆