在Java Swing編程過程中經常需要處理鍵盤事件例如處理快捷鍵等這裡就介紹如何定義鍵盤事件以及如何處理這些事件
在jdk中分別針對Jcomponent和Text類的對象定制了不同的處理鍵盤事件的方法在Jcomponent中定義了registerKeyboardAction方法使用這個方法來將需要處理的鍵盤事件以及處理事件的行為綁定在一起Text類中具有keymap對象同Jcomponent中的處理方法類似這個對象保存著需要處理的鍵盤事件和對應的行為
而在jdk中使用一種新的方法來處理鍵盤事件它將jdk的兩種方法整合在一起不需要區分被處理的是Jcomponent還是Text類型的組件它定義了兩個新的類InputMap和ActionMap他們均是簡單的表或映射一個InputMap將一個Keystroke對應到一個對象ActionMap將一個對象對應到一個行為(Action)通常InputMap中KeyStroke所對應的對象是一個字符串通過這個字符串可以在ActionMap中查找到相應的行為
InputMap和ActionMap中均有put方法InputMap的put方法可以將Keystroke對應到一個對象而ActionMap的put方法可以將一個對象對應到一個行為
在每一個Jcomponent組件中會有三個缺省的InputMap和一個缺省的ActionMap他們可以通過調用getInputMap(int condition)和getActionMap()得到三個InputMap分別是當組件本身擁有焦點時的InputMap(WHEN_FOCUSED)當組件的祖先擁有焦點時的InputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)和組件所在的窗體具有焦點時的InputMap(WHEN_IN_FOCUSED_WINDOW)(括號內表示為了得到這些InputMap應該在getInputMap中設置的參數)以下分別說明這三種InputMap
組件本身擁有焦點時的InputMap當組件擁有焦點時鍵盤按鍵按下則java在這個InputMap中查找鍵盤事件所對應的KeyStroke對象
組件的祖先擁有焦點時的InputMap當組件的祖先擁有焦點時鍵盤按鍵按下則java查找這個InputMap
組件所在的窗口擁有焦點時的InputMap當組件所在的窗口具有焦點時鍵盤按鍵按下則java查找這個InputMap
當一個鍵被按下這個事件被轉化成一個KeyStroke對象java會查找這個Jcomponent的相應InputMap(例如當組件的祖先具有焦點時java就查找這個Jcomponent的祖先擁有焦點的InputMap)中是否有這個KeyStroke如果有取出它所對應的對象(通常是字符串)利用這個對象在這個Jcomponent的ActionMap中查找如果找到對應的行為(Action)則java執行這個行為的actionPerformed方法(隨後介紹這個方法)從而達到處理鍵盤事件的目的
每一個InputMap可以具有parent屬性這個屬性的值是一個InputMap當在一個InputMap中查找不到鍵盤事件的KeyStroke時java會自動在它的parent屬性指定的InputMap中查找依次向上查找直至找到使用parent的好處是當有一些固定的不希望用戶進行改動的鍵盤映射可以存放在parent屬性所指定的InputMap中從而避免被意外修改;另外可以將多個Jcomponent的缺省InputMap設置具有相同的parent使得可以共享一些鍵盤綁定的設置可以通過InputMap類的setparent()方法設置它的parent屬性ActionMap也具有相同的parent屬性使用方法也相同
以上是如何將一個鍵盤事件對應到一個行為以下就簡單介紹行為(Action)
行為是一個實現了Action接口的類在Action接口中定義了個方法其中最關鍵的是actionPerformed()方法這個方法描述了這個行為的具體操作過程其他幾個方法包括setEnabledisEnabledputValuegetValueaddPropertyChangeListener和removePropertyChangeListener方法他們分別用來設置行為是否可用判斷行為可用的狀態設置和取得行為的一些屬性最後兩個方法用來允許其他對象在行動對象的屬性發生變化後得到通知
通常我們使用一個實現了Action接口的大部分方法的抽象類AbstractAction類作為基類重載actionPerformed方法以實現我們的行為
我們用一個例子來具體說明如何進行實際的操作
首先編寫一個具體的行為對指定的鍵盤事件進行處理
public class TextAction extends AbstractAction
{
private String a;
public TextAction(String a)
{ thisa = a; }
public void actionPerformed(ActionEvent parm)
{
String b = parmgetActionCommand(); //得到行為的命令字符串
Systemoutprintln(command=+b);
Systemoutprintln(prompt=+thisa);
}
}
建立四個TextAction對象
TextAction whenFocusSon = new TextAction(focus son);
TextAction whenFocusFather = new TextAction(focus father);
TextAction window = new TextAction(window);
TextAction ancestor = new TextAction(ancestor);
隨後在一個窗體中加入兩個面板名為sonPanel和parentPanel使得parentPanel是sonPanel的祖先並在sonPanel中加入一個名為son的button在parentPanel中加入名為parent的button在fatherPanel外加入幾個button
得到son組件的三個InputMap並創建一個名為focusFatherIm的InputMap使得這個InputMap成為focusIm的parent
//get default inputMap (when focus inputmap) and set a parent InputMap
focusIm = songetInputMap();
focusFatherIm = new InputMap();
focusImsetParent(focusFatherIm);
//get WHEN_ANCESTOR_OF_FOCUSED_COMPONENT inputMap
ancestorIm = songetInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
//get WHEN_IN_FOCUSED_WINDOW inputMap
windowIm = songetInputMap(WHEN_IN_FOCUSED_WINDOW);
//在這些InputMap中分別加入鍵盤綁定
focusImput(KeyStrokegetKeyStroke(f)actionFocusSon);
focusFatherImput(KeyStrokegetKeyStroke(F)actionFocusFather);
ancestorImput(KeyStrokegetKeyStroke(a)actionAncestor);
windowImput(KeyStrokegetKeyStroke(w)actionWindow);
//得到son組件的缺省的ActionMap並將已經建立的行為與特定的對象(字符串)進行綁定
am = songetActionMap();
amput(actionFocusSonwhenFocusSon);
amput(actionFocusFatherwhenFocusFather);
amput(actionAncestorancestor);
amput(actionWindowwindow);
運行程序及其相應結果
單擊son按鈕這時如果按下fFaw程序均會有相應的輸出這是因為此時的焦點在son按鈕上而son按鈕組件的三個InputMap都是有效的所以他們對應的事件都會發生
單擊parent按鈕這時按下w程序會有相應的輸出而按下fFa程序沒有反應這是因為parent按鈕具有焦點這個按鈕不是son按鈕的祖先而son所在的窗口具有焦點所以只有組件所在窗口具有焦點的InputMap是有效的
單擊其他的按鈕(parentPanel外的按鈕)這時按下w程序會有相應的輸出而按下fFa程序沒有反應這是因為這些按鈕具有焦點他們不是son按鈕的祖先而son所在的窗口具有焦點所以只有組件所在窗口具有焦點的InputMap是有效的
附主要程序代碼
import javaawt*;
import javaxswing*;
import comborlandjbcllayout*;
import javaawteventActionEvent;
import javaawteventActionListener;
import comsunjavaswingplafmotif*;
public class EventPanel extends JPanel implements ActionListener
{
JButton btnYellow = new JButton();
JButton btnBlue = new JButton();
JButton btnRed = new JButton();
JPanel parentPanel = new JPanel();
JPanel sonPanel = new JPanel();
XYLayout xYLayout = new XYLayout();
JButton son = new JButton();
JButton parent = new JButton();
public EventPanel()
{
try{
jbInit();
}catch(Exception ex)
{ exprintStackTrace(); }
}
void jbInit() throws Exception
{
btnYellowsetText(Yellow);
btnYellowsetBounds(new Rectangle( ));
thissetLayout(null);
btnBluesetBounds(new Rectangle( ));
btnBluesetText(Blue);
btnRedsetBounds(new Rectangle( ));
btnRedsetText(Red);
parentPanelsetBorder(BorderFactorycreateRaisedBevelBorder());
parentPanelsetBounds(new Rectangle( ));
parentPanelsetLayout(xYLayout);
sonPanelsetBorder(BorderFactorycreateLoweredBevelBorder());
sonsetText(son);
parentsetText(parent);
thisadd(btnYellow null);
thisadd(btnBlue null);
thisadd(btnRed null);
thisadd(parentPanel null);
parentPaneladd(sonPanel new XYConstraints( ));
sonPaneladd(son null);
parentPaneladd(parent new XYConstraints( ));
btnYellowaddActionListener(this);
btnRedaddActionListener(this);
btnBlueaddActionListener(this);
InputMap focusImfocusFatherImancestorImwindowIm;
ActionMap am;
//create four TextAction for diff purpose
TextAction whenFocusSon = new TextAction(focus son);
TextAction whenFocusFather = new TextAction(focus father);
TextAction window = new TextAction(window);
TextAction ancestor = new TextAction(ancestor);
//get default inputMap (when focus inputmap) and set a parent InputMap
focusIm = songetInputMap();
focusFatherIm = new InputMap();
focusImsetParent(focusFatherIm);
//get WHEN_ANCESTOR_OF_FOCUSED_COMPONENT inputMap
ancestorIm = songetInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
//get WHEN_IN_FOCUSED_WINDOW inputMap
windowIm = songetInputMap(WHEN_IN_FOCUSED_WINDOW);
//put the keyStroke to the InputMap
focusImput(KeyStrokegetKeyStroke(f)actionFocusSon);
focusFatherImput(KeyStrokegetKeyStroke(F)actionFocusFather);
ancestorImput(KeyStrokegetKeyStroke(a)actionAncestor);
windowImput(KeyStrokegetKeyStroke(w)actionWindow);
//get the actionMap
am = songetActionMap();
amput(actionFocusSonwhenFocusSon);
amput(actionFocusFatherwhenFocusFather);
amput(actionAncestorancestor);
amput(actionWindowwindow);
}
public void actionPerformed(ActionEvent e)
{
//this code is used to change the backgracolor
Object source=egetSource();
Color color=null;//=getBackground();
if (source==btnYellow) color=Coloryellow;
else if (source==btnRed) color = Colorred;
else if (source == btnBlue) color = Colorblue;
setBackground(color);
repaint();
}
}
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26711.html