将密钥绑定到JButton

时间:2016-02-07 21:19:11

标签: java swing key-bindings

我一直在寻找一个答案,将键绑定附加到JButton很多个小时,但仍然无法做到。 我有以下简单的程序,包括两个类。我试过用几种方法使用getInputMap()和getActionMap(),但没有成功。我希望它能做到以下几点: 当我按下键盘上的“1”键时,它会按下JButton btn1,当我按下“2”键时,它会按下JButton btn2(因此1或2会出现在JLabel上)。

//的Class1://

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;

public class event06 extends JFrame {

    event06b base = new event06b(this);

    JButton btn1 = new JButton("1");
    JButton btn2 = new JButton("2");
    JLabel label = new JLabel("");

    public event06() {
        super();
        setBounds(300,300, 200,150);
        setResizable(true);
        setTitle("Button with keybinding");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        btn1.addActionListener(base);
        btn2.addActionListener(base);

        FlowLayout flo = new FlowLayout(FlowLayout.CENTER);
        setLayout(flo);
        add(btn1);
        add(btn2);
        add(label);

        setVisible(true);
    }

    public static void main(String[] args) {
        event06 window = new event06(); 
    }
}


//class 2://
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;

public class event06b implements ActionListener {
    event06 gui;

    public event06b (event06 in) {
        gui = in;
    }
        public void actionPerformed(ActionEvent pressed) {
            Object source = pressed.getSource();
            if (source == gui.btn1) {gui.label.setText("1");}
            else if (source == gui.btn2) {gui.label.setText("2");}
        }
}

更新: (我仍然没有15的声誉,所以我无法回答我自己的问题,据我所知,我不能在评论中发布代码或长答案,所以我正在修改我的问题。)

我设法发现,如果没有按钮具有焦点,则仅使用KeyListeners。 请参阅以下示例:

 //in class 1:// 
FlowLayout flo = new FlowLayout(FlowLayout.CENTER);
    setLayout(flo);
    add(btn1);
    btn1.setEnabled(false);
    btn2.setEnabled(false);
    add(btn2);
    add(label);

    btn1.addActionListener(base);
    btn2.addActionListener(base);
    addKeyListener(base);

这里,两个按钮btn1和btn2被禁用,因此它们没有焦点,而是窗口处于焦点上。这就是KeyListener可以工作的原因:

public void keyPressed (KeyEvent evt) {
    int keycode = evt.getKeyCode();
    gui.label.setText(Integer.toString(keycode));
}

public void keyReleased(KeyEvent txt) {}
public void keyTyped(KeyEvent txt) {}

在这种情况下,class1中的JLabel显示已按下的键的键代码。 (注意,您可以在keyPressed方法下获取keycode,而不是在keyTyped方法下 - 后者适合使用getKeyChar获取关键字符。使用getKeyCode而不是getKeyChar也更好,因为特定键具有键码,但不是keychar)。

对于按钮,我使用actionPerformed方法:

public void actionPerformed(ActionEvent pressed) {
    Object source = pressed.getSource();
    if (source == gui.btn1) {gui.label.setText("1");}
    else if (source == gui.btn2) {gui.label.setText("2");}
}

由于此处禁用了按钮,因此无效。到目前为止,我无法将keyCode连接到此actionPerformed方法。 在Veluria提供的示例中,此actionPerformed方法是AbstractAction的一部分,并且在那里使用了InputMaps和ActionMaps。 这似乎是正确的答案,虽然我在尝试使用该建议时遇到此错误: 错误:预期的标识符

YEAH,我找到了解决方案!!!: (首先我告诉你代码,然后我将解释我修改过的内容。)

// class 1://

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class event06 extends JFrame {

    event06b base = new event06b(this);

    JButton btn1 = new JButton("1");
    JButton btn2 = new JButton("2");
    JLabel label = new JLabel("");


    public event06() {
        super();
        setBounds(300,300,250,75);
        setResizable(false);
        setTitle("Buttons with key");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        FlowLayout flo = new FlowLayout(FlowLayout.CENTER);
        setLayout(flo);
        add(btn1);
        btn1.setEnabled(true);
        btn2.setEnabled(true);
        add(btn2);
        add(label);

        btn1.addActionListener(base.act);       
        btn1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke('1'), "pressed");
        btn1.getActionMap().put("pressed", base.act);

        btn2.addActionListener(base.act);
        btn2.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke('2'), "pressed");
        btn2.getActionMap().put("pressed", base.act);


        setVisible(true);
    }

    public static void main(String[] args) {
        event06 window = new event06();
    }
}

等级2:

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;

public class event06b {
    event06 gui;

    public event06b (event06 in) {
        gui = in;
    }

    Action act = new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent pressed) {
            Object source = pressed.getSource();
            if (source == gui.btn1) {gui.label.setText("1");}
            else if (source == gui.btn2) {gui.label.setText("2");}
        }
    };
}

所以,我做了以下事情: - 在类1中将一个ActionListener添加到btn1和btn2:

btn1.addActionListener(base.act);
  • 我还使用了InputMap:

    btn1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke('1'),“press”);

  • 这里要注意两件事:您必须将“JComponent.WHEN_IN_FOCUSED_WINDOW”文本放在圆括号中,这样即使按钮没有焦点,您也可以从键中获取输入。另一件事是,当你使用getKeyStroke('1')时,你必须给一个字符,所以使用''代替“”。 (我看到“”在很多例子中使用过。)

然后我使用了ActionMap,如下所示:

btn1.getActionMap().put("pressed", base.act);

请注意,在这里,也在ActionListener中,我通过使用base.act引用其他类(base指的是class2,而act指的是Action里面)

在class2中,我将actionPerformed方法放在AbstractAction中,并使用@Override。我不知道,为什么必须使用@Override,因为没有它也可以使用。

对不起,如果我误解了某些内容而没有给出正确的解释。我只是一个爱好程序员,没有计算机科学的教育。但我希望,这个问题和所提供的答案可能会为许多其他人提供帮助。

1 个答案:

答案 0 :(得分:4)

这是一种方法:

Action action = new AbstractAction("1") {
    @Override
    public void actionPerformed(ActionEvent e) {
        label.setText("1");
    }
};
action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("1"));
btn1.setAction(action);
btn1.getActionMap().put("setOneAction", action);
btn1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
    (KeyStroke) action.getValue(Action.ACCELERATOR_KEY), "setOneAction");