2011-12-15 63 views
9

註冊鍵空間時,按空格鍵,然後按ctrl(「空格鍵」和「釋放空格鍵」或任何其他修飾鍵),然後釋放空間並最終釋放Ctrl將導致與「SPACE」相關的操作被執行,但不會執行與「釋放SPACE」相關的操作。java swing鍵綁定 - 丟失釋放的鍵的操作

一旦空間不再被按下(或同時按下一個修飾鍵)就會執行動作的首選方式是什麼?我只在Windows 7,64位上試過。

import javax.swing.SwingUtilities; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.AbstractAction; 
import javax.swing.KeyStroke; 
import java.awt.event.ActionEvent; 
import java.awt.Cursor; 

class Bind extends JPanel { 
    { 
    getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed"); 
    getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released"); 
    getActionMap().put("pressed", new AbstractAction() { 
     @Override public void actionPerformed(ActionEvent e) { 
     System.out.println("pressed"); 
     setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 
     } 
    }); 
    getActionMap().put("released", new AbstractAction() { 
     @Override public void actionPerformed(ActionEvent e) { 
     System.out.println("released"); 
     setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
     } 
    }); 
    } 
    public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override public void run() { 
     JFrame f = new JFrame("Key Bindings"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new Bind()); 
     f.setSize(640, 480); 
     f.setVisible(true); 
     } 
    }); 
    } 
} 

UPDATE:這是爲了避免粘空間的方式時意外擊中CTRL,ALT或釋放空間之前移位:

import javax.swing.SwingUtilities; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.AbstractAction; 
import javax.swing.KeyStroke; 
import java.awt.event.ActionEvent; 
import java.awt.Cursor; 

class Bind extends JPanel { 
    { 
    getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed"); 
    getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released"); 
    getInputMap().put(KeyStroke.getKeyStroke("ctrl released SPACE"), "released"); 
    getInputMap().put(KeyStroke.getKeyStroke("shift released SPACE"), "released"); 
    getInputMap().put(KeyStroke.getKeyStroke("shift ctrl released SPACE"), "released"); 
    getInputMap().put(KeyStroke.getKeyStroke("alt released SPACE"), "released"); 
    getInputMap().put(KeyStroke.getKeyStroke("alt ctrl released SPACE"), "released"); 
    getInputMap().put(KeyStroke.getKeyStroke("alt shift released SPACE"), "released"); 
    getInputMap().put(KeyStroke.getKeyStroke("alt shift ctrl released SPACE"), "released"); 
    getActionMap().put("pressed", new AbstractAction() { 
     @Override public void actionPerformed(ActionEvent e) { 
     System.out.println("pressed"); 
     setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 
     } 
    }); 
    getActionMap().put("released", new AbstractAction() { 
     @Override public void actionPerformed(ActionEvent e) { 
     System.out.println("released"); 
     setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
     } 
    }); 
    } 
    public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override public void run() { 
     JFrame f = new JFrame("Key Bindings"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new Bind()); 
     f.setSize(640, 480); 
     f.setVisible(true); 
     } 
    }); 
    } 
} 
+2

爲了更快提供更好的幫助,請發佈[SSCCE](http://sscce.org/)。 – 2011-12-15 18:56:46

+2

[SSCCE](http://sscce.org/)爲更好的幫助更快地添加:-) – Aksel 2011-12-15 19:08:22

+1

行..這是一個非常好的問題。我看到你描述的行爲(在32位Win 7中),但不知道如何解決它。希望有一位鍵綁定的大師會由..soon發生。 :) – 2011-12-15 19:24:12

回答

6

有意義的是,當控制鍵仍然處於按下狀態時,未觸發released SPACE事件。我期望一個control released SPACE事件被解僱。

添加以下代碼:

getInputMap().put(KeyStroke.getKeyStroke("control released SPACE"), "released"); 

出於同樣的原因,如果你先按住Ctrl鍵向下SPACE事件將不會觸發。所以你還需要爲control SPACE添加綁定。

您需要爲所有修飾鍵執行此操作,這可能是也可能不是跟蹤關鍵事件的簡單解決方案。

3

這有可能是你的操作系統不火keyReleased事件,但只有keyPressedkeyTyped事件或其他組合,因此請先檢查。你可能只需要檢查keyTyped事件而不是keyReleased,你就可以完成它。

簡短的回答:

使用bitmask或數組來跟蹤哪些鍵是目前正處於「按下」狀態,然後使用這些值來觸發事件。也就是說,不要直接使用Swing事件來觸發應用程序中的響應 - 您需要一個額外的圖層來存儲鍵盤的狀態,並從該狀態開始採取相關操作。

還有一些方法可用(see the end of this tutorial - "isAltDown", "isCtrlDown" etc.)來檢查當您按下「空格」鍵等事件時是否按下修飾鍵。

龍答:

你是正確的,當得到按下和釋放按鍵事件會被解僱。它必須以這種方式工作,以便您可以支持應該單獨處理這些事件的應用程序,而不是一起處理這些事件。一個例子(儘管這不是唯一的例子)是PC上的視頻遊戲,你可能會一次按下多個字母/修飾鍵(例如,A左轉,W前進),遊戲必須處理這兩個事件作爲不同的輸入,而不是複合輸入,導致您的移動向左前進。

因此,如果您需要處理複合輸入,您基本上想要做的事情是讓您的應用程序需要響應的操作及其相關聯的鍵綁定(無論是單鍵還是多鍵)真的不重要)。當一個鍵被按下時,你基本上會打開一個表示當前「按下」的鍵的標誌,並在標誌釋放時清除標誌。然後,爲了觸發你的事件,你只需要檢查所有被按下的鍵(通過檢查哪個鍵「標誌」處於活動狀態),並且如果按下了特定事件的組合鍵,則事件被觸發。

如果觸發事件的鍵數少於32個,那麼實際上可以使用bitmask和32位int值而不是數組來執行此操作。事實上,如果可以的話,這樣做更簡單。如果您最多需要64個密鑰,請使用long做同樣的事情。如果觸發事件的鍵很少(例如8個或更少),則可以使用8位short類型。