2012-05-22 28 views
3

我試圖得到一個簡單的JFrame一個按鈕開火時,這些事件的發生的事件:回車鍵是消防用空格鍵一個JButton,或回車鍵,或者鼠標點擊

  • 按下並且JButton具有焦點
  • 空格鍵被按下且JButton具有焦點
  • 單擊JButton。

看來,輸入和空格鍵一起「免費」,以及在JButton上使用addActionListener的默認鼠標點擊;麻煩的是,我讀過關鍵綁定依賴於使用的外觀和感覺。

我試圖通過向JButton的動作地圖添加Enter和空格鍵來獲得LaF的通用行爲,甚至添加了一個隨機密鑰(「m」)來確保ActionMap正在執行這項工作(它是),但現在鼠標點擊丟失了。我似乎能夠獲得所有按鍵和鼠標點擊的唯一方法是同時使用動作貼圖和addActionListener。

有沒有辦法讓這些鍵和鼠標綁定在所有LaF上一致地工作,而不嘗試檢測可能會出現的每個可能的LaF?我可以註冊一個將觸發鍵盤和鼠標事件的單個動作偵聽器嗎?

我最喜歡的解決方案是將鼠標點擊添加到JButton動作地圖,並檢測在動作內部發生了哪個按鍵或鼠標點擊。

我仍然在這裏學習繩索,所以這可能不是最好或最有效的方式來做事情;我相信它是過度設計的。這是一種訓練練習,我正在試驗一切我能得到的東西。歡迎任何和所有的編碼風格評論!

import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 

import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.InputMap; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.UIManager; 

public class Example extends JFrame { 

// ============================ 
private class BtnListener extends AbstractAction { 
    private static final long serialVersionUID = 1L; 

    public void actionPerformed(ActionEvent ae) { 
     System.out.println("\nclick button listener triggered"); 
     System.out.println(ae.getSource().getClass().toString()); 
    } 
} // class BtnListener 

private static final int NO_MODIFIER = 0; 
private static final boolean ON_KEY_PRESS = false; 
private static final KeyStroke ENTER_PRESSED = KeyStroke.getKeyStroke(
     KeyEvent.VK_ENTER, NO_MODIFIER, ON_KEY_PRESS); 
private static final KeyStroke M_PRESSED = KeyStroke.getKeyStroke(
     KeyEvent.VK_M, NO_MODIFIER, ON_KEY_PRESS); 
private static final KeyStroke SPACEBAR_PRESSED = KeyStroke.getKeyStroke(
     KeyEvent.VK_SPACE, NO_MODIFIER, ON_KEY_PRESS); 
private JButton btnButton; 
private final AbstractAction btnListener = new BtnListener(); 
private JPanel buttonPanel; 
private JFrame frmMain; 

public static void main(String[] args) { 
    Example ex = new Example(); 
    ex.displayFrame(); 
} 

Action btnActionListener = new AbstractAction() { 
    private static final long serialVersionUID = 1L; 

    public void actionPerformed(ActionEvent e) { 
     System.out.println("\nkey button action triggerred"); 
     System.out.println(e.getSource().getClass().toString()); 
     if (e.getSource() instanceof JButton) { 
      System.out.println("button"); 
     } else { 
      System.out.println("Something else"); 
     } 
    } 
}; 

public Example() { 
    initialize(); 
} 

public void displayFrame() { 
    try { 
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
    } catch (Throwable e) { 
     e.printStackTrace(); 
    } 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       frmMain.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

private void initialize() { 

    frmMain = new JFrame(); 
    btnButton = new JButton("Abutton"); 

    // Comment this out, you lose the mouse click 
    btnButton.addActionListener(btnListener); 

    // Comment out ActionMaps, but keep addActionListner (above), and 
      // only lose M_PRESSED 
    InputMap buttonFocusedMap = btnButton 
      .getInputMap(JComponent.WHEN_FOCUSED); 

    buttonFocusedMap.put(ENTER_PRESSED, "blah"); 
    btnButton.getActionMap().put("blah", btnActionListener); 

    buttonFocusedMap.put(SPACEBAR_PRESSED, "blort"); 
    btnButton.getActionMap().put("blort", btnActionListener); 

    buttonFocusedMap.put(M_PRESSED, "gaaak"); 
    btnButton.getActionMap().put("gaaak", btnActionListener); 

    // Is there a way to add a mouse click to the ActionMap? 

    buttonPanel = new JPanel(); 
    buttonPanel.add(btnButton); 

    frmMain.getContentPane().add(buttonPanel); 
    frmMain.setBounds(100, 100, 500, 432); 
    frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
} 

} 

回答

9

BasicButtonListener,通過BasicButtonUI使用,確保所有按鈕(檢查,電臺,切換)綁定到空間當重點。這可以跨平臺運行,即使單個外觀感覺可能會呈現各種按鈕模型狀態。按空間喚起按下UIAction,並釋放空間喚起發佈UIAction。鼠標在按鈕邊界內按下並釋放時也會發生同樣的情況;在按下按鈕的同時拖出按鈕以查看武裝狀態更改。

在這兩種情況下,組合壓制發佈調用您的按鈕的actionPerformed()方法。結合輸入Action,不管聚焦的

一種方便的方式,是通過根窗格的setDefaultButton()方法。這example說明了點擊一個按鈕的所有三種方法。

+1

非常好!感謝您的深入解釋。 –

0

你可以(也可能應該)做的是創建一個AbstractAction。您可以使用AbstractAction這對你的ActionMap以及爲點擊(不JButton.setAction(...))