2014-09-18 68 views
1

我對Swing相當陌生,並且無法理解KeyBinding概念。 我正在嘗試將JButton添加到我的JPanel,然後設置其操作命令和KeyBinding。這裏是我的代碼:JButton KeyBinding和setActionCommand

JButton b = new JButton("1"); 
MyAction myaction = new MyAction("1"); 
b.setAction(myaction); 
b.getInputMap(JButton.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), "one"); 
b.getActionMap().put("one", myaction); 
b.setActionCommand("one"); 

MyAction這裏,是一個內部類

class MyAction extends AbstractAction { 
    public MyAction(String text) { 
     super(text); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     System.out.println("Action command is: " + e.getActionCommand()); 
    } 
} 

現在,如果我按下按鈕,我得到這樣的輸出:

Action command is: one 

但是,如果我按' 1'在鍵盤上,我得到這個:

Action command is: 1 

這是爲什麼?我應該怎麼做才能得到相同的動作命令,而不管動作是由按鈕按下還是按鍵綁定?

+1

你將它綁定到0鍵不是1鍵。 – 2014-09-18 21:59:25

+0

對不起,我在這裏貼錯了代碼。編輯它。 – Siddharth 2014-09-18 22:00:35

回答

2

考慮設置操作命令鍵在AbstractAction本身:

class MyAction extends AbstractAction { 
    public MyAction(String text) { 
     super(text); 
     putValue(ACTION_COMMAND_KEY, "one"), 
    } 
    //... 

例如:

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

public class Foo2 extends JPanel { 
    private static final String[] NUMBER_TEXTS = { 
     "one", "two", "three", "four", "five" 
    }; 


    public Foo2() { 

     for (int i = 0; i < NUMBER_TEXTS.length; i++) { 
     String numberString = String.valueOf(i + 1); 
     Action numberBtnAction = new NumberBtnAction(numberString, NUMBER_TEXTS[i]); 
     JButton btn = new JButton(numberBtnAction); 
     InputMap inMap = btn.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); 
     ActionMap actionMap = btn.getActionMap(); 

     KeyStroke keyStroke = KeyStroke.getKeyStroke(numberString.charAt(0)); 
     inMap.put(keyStroke, NUMBER_TEXTS[i]); 
     actionMap.put(NUMBER_TEXTS[i], numberBtnAction); 

     add(btn); 
     } 

    } 

    private class NumberBtnAction extends AbstractAction { 
     public NumberBtnAction(String numberString, String numberText) { 
     super(numberString); 
     putValue(ACTION_COMMAND_KEY, numberText); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     System.out.println(e.getActionCommand()); 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("Foo2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new Foo2()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

編輯
或者,你可以有一個獨立的鍵綁定只需按下按鈕的動作:

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

public class Foo2 extends JPanel { 
    private static final String[] NUMBER_TEXTS = { 
     "one", "two", "three", "four", "five" 
    }; 


    public Foo2() { 

     for (int i = 0; i < NUMBER_TEXTS.length; i++) { 
     String numberString = String.valueOf(i + 1); 
     Action numberBtnAction = new NumberBtnAction(numberString, NUMBER_TEXTS[i]); 
     JButton btn = new JButton(numberBtnAction); 
     Action pressBtnAction = new PressButtonAction(btn); 
     InputMap inMap = btn.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); 
     ActionMap actionMap = btn.getActionMap(); 

     KeyStroke keyStroke = KeyStroke.getKeyStroke(numberString.charAt(0)); 
     inMap.put(keyStroke, NUMBER_TEXTS[i]); 
     //!! actionMap.put(NUMBER_TEXTS[i], numberBtnAction); 
     actionMap.put(NUMBER_TEXTS[i], pressBtnAction); 

     add(btn); 
     } 

    } 

    private class NumberBtnAction extends AbstractAction { 
     public NumberBtnAction(String numberString, String numberText) { 
     super(numberString); 
     putValue(ACTION_COMMAND_KEY, numberText); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     System.out.println(e.getActionCommand()); 
     } 
    } 

    private class PressButtonAction extends AbstractAction { 
     private AbstractButton btn; 

     public PressButtonAction(AbstractButton btn) { 
     this.btn = btn; 
     } 


     @Override 
     public void actionPerformed(ActionEvent e) { 
     btn.doClick(); 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("Foo2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new Foo2()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 
+0

通過使用'putValue(ACTION_COMMAND_KEY,numberText);'沒有不同'Action按鈕按下和按鍵時仍然會觸發? 'btn.doClick()'是一個解決方法,但是在創建JButton時,我是否沒有辦法在兩者上都有相同的操作? – Siddharth 2014-09-18 22:29:14

+0

@Siddharth:沒有相同的動作在我的第一個代碼示例中被觸發。 – 2014-09-18 22:31:23

2

在激活的內容上有所不同。當你按下按鈕,該按鈕被激活,因此它是當你按下鍵actionCommand是被播種爲的ActionEvent

一部分,Action,與密鑰關聯綁定被激活,它是使用您提供的文本作爲actionCommand

如果你要使用兩個相同的動作,然後播種Action這兩個鍵綁定和按鈕...

MyAction myaction = new MyAction("1"); 
JButton b = new JButton(myaction); 
b.setAction(myaction); 
b.getInputMap(JButton.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), "one"); 
b.getActionMap().put("one", myaction); 

這樣,當按鈕被激活或大骨節病> 1鍵被按下時,將使用相同的Action ...這是種Action小號

更新點的

由於某種原因,它仍然不能解決它。我得到相同的輸出

嗯,我不知道你在做什麼,但它對我來說工作正常...

import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestAction { 

    public static void main(String[] args) { 
     new TestAction(); 
    } 

    public TestAction() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      JButton b = new JButton("1"); 
      MyAction myaction = new MyAction("1"); 
      b.setAction(myaction); 
      b.getInputMap(JButton.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_1, 0), "one"); 
      b.getActionMap().put("one", myaction); 
      //b.setActionCommand("one"); 
      b.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        System.out.println(e.getActionCommand()); 
       } 
      }); 

      add(b); 
     } 

    } 

    class MyAction extends AbstractAction { 

     public MyAction(String text) { 
      super(text); 
      putValue(ACTION_COMMAND_KEY, "one"); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println("Action command is: " + e.getActionCommand()); 
     } 
    } 

} 

更新

基於在評論中鏈接的示例中,添加到putValue(ACTION_COMMAND_KEY, "one");MyAction,將打印one無論動作的觸發方式。

事實上,我會擺脫setActionCommand調用按鈕。

事實上,使用Action■當,我甚至不與動作命令麻煩,因爲Action是自包含的,哪一種的點...

+0

對於正在激活的不同操作,您是正確的,但出於某種原因,它仍不能解決問題。我得到相同的輸出。 – Siddharth 2014-09-18 22:23:23

+0

你會得到兩個不同的結果(應用Action後)的唯一原因可能是因爲你仍然有一個'JButton'的ActionListener',你不需要它... – MadProgrammer 2014-09-18 22:30:24

+0

適合我的工作,請參閱更新 – MadProgrammer 2014-09-18 22:33:16