2016-02-07 2 views
1

Je cherchais une réponse pour attacher un raccourci clavier à un JButton pendant de nombreuses heures, mais je n'ai toujours pas réussi à le faire. J'ai le programme simple suivant composé de deux classes. J'ai essayé d'utiliser getInputMap() et getActionMap() de plusieurs façons, mais sans succès. Je veux qu'il fasse ce qui suit: Quand j'appuie sur la touche "1" du clavier, il appuie sur JButton btn1, et quand j'appuie sur la touche "2", il appuie sur JButton btn2 (et 1 ou 2 apparaît sur JLabel en conséquence).Relier une clé à un 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");} 
     } 
} 

Mise à jour: (je n'ai toujours pas une réputation de 15 encore, je ne peux pas répondre à ma propre question, et pour autant que je sache, je ne peux pas poster codes ou de longues réponses dans les commentaires, donc je modifie ma question à la place).

Ce que j'ai réussi à découvrir, c'est que l'utilisation de KeyListeners ne fonctionne que si aucun bouton n'a le focus. Voir l'exemple suivant:

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

Ici, les deux boutons, btn1 et BTN2 sont désactivés, ils n'ont pas mise au point, au lieu de la fenêtre est mise au point. Voilà pourquoi le KeyListener peut fonctionner:

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

Dans ce cas, tha JLabel à Class1 montre le code d'activation de la clé qui a été pressé. (Remarquez que vous pouvez obtenir le code clé sous la méthode keyPressed, et non sous la méthode keyTyped - ce dernier est bon pour obtenir un caractère clé en utilisant getKeyChar Il est également préférable d'utiliser getKeyCode au lieu de getKeyChar, car certaines touches ont un code clé , mais pas un keychar).

Pour les boutons que j'utilise la méthode 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");} 
} 

Puisque les boutons sont désactivés ici, cela ne fonctionne pas. Jusqu'à présent, je ne pouvais pas connecter le keyCode à cette méthode actionPerformed. Dans l'exemple présenté par Veluria, cette méthode actionPerformed fait partie d'une AbstractAction, et InputMaps et ActionMaps y ont été utilisés. Cela semble être la bonne réponse ici, même si je reçois cette erreur, quand je suis en train d'utiliser cette suggestion: erreur: identifiant prévu

OUAIS, je trouvé la solution !!!: (premier je montre vous le code, alors je vais vous expliquer ce que j'ai modifié).

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

Alors, je l'ai fait ce qui suit: - Ajout d'une ActionListener en classe 1 à BTN1 et BTN2:

btn1.addActionListener(base.act); 
  • I également utilisé le InputMap:

    btn1.getInputMap (JComponent.WHEN_IN_FOCUSED_WINDOW) .put (KeyStroke.getKeyStroke ('1'), "pressé"); Deux choses à noter ici: Vous devez mettre le texte "JComponent.WHEN_IN_FOCUSED_WINDOW" entre crochets, afin que vous puissiez obtenir l'entrée de la touche même lorsque le bouton n'a pas le focus. L'autre chose est que lorsque vous utilisez getKeyStroke ('1'), vous devez donner un caractère, alors utilisez '' au lieu de "". (J'ai vu "" être utilisé dans de nombreux exemples).

Je l'utilise ActionMap, comme ceci:

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

S'il vous plaît noter que ici, et aussi au ActionListener, je faisais référence à l'autre classe en utilisant base.act (base fait référence en class2, et act fait référence à l'action à l'intérieur)

En classe2, j'ai mis la méthode actionPerformed dans AbstractAction, et utilisé @Override. Je ne sais pas pourquoi @Override doit être utilisé, car il fonctionne aussi sans. Je suis désolé si j'ai mal interprété quelque chose et que je n'ai pas donné la bonne explication. Je suis juste un programmeur amateur, n'ayant aucune éducation en informatique. Mais j'espère que cette question et la réponse fournie pourraient aider beaucoup d'autres à être dans le même bateau.

+0

Regardez dans KeyListener https://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyListener.html – JackVanier

+0

Merci pour la suggestion. J'ai essayé cela, et dans un autre programme a réussi à lier un KeyEvent à la même action que ce que fait le JButton, mais cela ne fonctionnait que lorsque le bouton avait le focus dessus. Dans ce cas, je n'ai pas utilisé getInputMap() et getActionMap(), mais un ActionEvent et un KeyEvent séparément. Ce que je voudrais vraiment faire ici est d'activer le bouton en appuyant sur une touche du clavier lorsque la fenêtre est active, et le bouton ne l'est pas. – CsJoe

+0

Alors que @JackWilliams signifie bien, ne pas considérer sa recommandation erronée. Vous êtes sur la bonne voie pour utiliser les raccourcis clavier ici et ** pas ** un KeyListener. –

Répondre

4

est ici une façon de le faire:

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

Merci @Velurie pour votre message utile! Sur la base de vos recommandations, après avoir modifié le programme, j'ai finalement réussi à le faire fonctionner. – CsJoe