2016-02-07 2 views
1

Я искал ответ, чтобы привязать привязку к JButton в течение многих-многих часов, и до сих пор не удалось это сделать. У меня есть следующая простая программа, состоящая из двух классов. Я попытался использовать getInputMap() и getActionMap() несколькими способами, но безуспешно. Я хочу, чтобы он делал следующее: Когда я нажимаю клавишу «1» на клавиатуре, он нажимает JButton btn1, и когда я нажимаю клавишу «2», он будет нажимать JButton btn2 (и 1 или 2 появится на JLabel, следовательно).Привязка ключа к JButton

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

Update: (я до сих пор не имеют репутацию 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) {} 

В этом случае, тх JLabel в class1 показывает клавиатурный код ключа, который был нажат. (Обратите внимание, что вы можете получить код ключа под методом keyPressed, а не под методом 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. Это, кажется, правильный ответ здесь, хотя я получаю эту ошибку, когда я пытаюсь использовать это предложение: ошибка: идентификатор ожидается

Да, я нашел решение !!!: (первый я показываю вы код, тогда я объясню, что я изменил).

// класс 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(); 
    } 
} 

class2:

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

Итак, я сделал следующее: - добавил ActionListener в классе от 1 до btn1 и btn2:

btn1.addActionListener(base.act); 
  • I также использовали InputMap:

    btn1.getInputMap (JComponent.WHEN_IN_FOCUSED_WINDOW) .put (KeyStroke.getKeyStroke ('1'), «нажата»);

  • Здесь нужно добавить текст «JComponent.WHEN_IN_FOCUSED_WINDOW» в круглых скобках, чтобы вы могли получить ввод от клавиши, даже если кнопка не имеет фокуса. Другое дело, что когда вы используете getKeyStroke ('1'), вы должны указать персонажа, поэтому используйте '' вместо "". (Я видел, что «используется во многих примерах»).

Тогда я использовал ActionMap, например, так:

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

Пожалуйста, обратите внимание, что здесь, а также на ActionListener, я имел в виду другой класс, используя base.act (база относится к классу2, а действие относится к действию внутри)

В классе2 я помещал метод actionPerformed внутри AbstractAction и использовал @Override. Я не знаю, почему @Override должен использоваться, потому что он также работает без него.

Прошу прощения, если я что-то неправильно истолковал и не дал правильного объяснения. Я просто программист по хобби, не имеющий образования в области компьютерных наук. Но я надеюсь, что этот вопрос и предоставленный ответ могут принести помощь многим другим, находящимся в одной лодке.

+0

Посмотрите в KeyListener https://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyListener.html – JackVanier

+0

Спасибо за предложение. Я попробовал это, и в другой программе удалось связать KeyEvent с тем же действием, что и JButton, но он работал только тогда, когда кнопка фокусировалась на нем. В этом случае я не использовал getInputMap() и getActionMap(), а ActionEvent и KeyEvent отдельно. Я действительно хотел бы сделать это, чтобы активировать кнопку, нажав клавишу клавиатуры, когда окно находится в фокусе, а кнопка - нет. – CsJoe

+0

Хотя @JackWilliams означает хорошо, не считайте его ошибочной рекомендацией. Вы на правильном пути, чтобы использовать привязки клавиш здесь, и ** не ** KeyListener. –

ответ

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"); 
+0

Спасибо @Veluria за полезное сообщение! Основываясь на ваших рекомендациях, после изменения программы мне удалось заставить ее работать. – CsJoe

Смежные вопросы