簡體   English   中英

java swing鍵綁定 - 釋放鍵的缺失操作

[英]java swing key bindings - missing action for released key

注冊了“SPACE”和“已發布的SPACE”的鍵綁定,當空間是唯一按下/釋放的鍵時,按照廣告的方式工作,我注意到按下空格,然后按ctrl(或任何其他修改鍵),然后釋放空間,最后釋放ctrl將導致執行與“SPACE”關聯的操作,但不會執行與“已釋放的SPACE”關聯的操作。

一旦不再按空格(或同時按下修改鍵),導致動作執行的首選方法是什么? 我只在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);
      }
    });
  }
}

更新 :這是在釋放空間之前意外點擊ctrl,alt或shift時避免粘滯空間的方法:

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

有意義的是,當Control鍵仍然按下時,不會觸發released SPACE事件。 我希望control released SPACE事件被解雇。

將以下內容添加到您的代碼中:

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

出於同樣的原因,如果您先按住Control鍵, SPACE事件將不會觸發。 因此,您還需要為control SPACE添加綁定。

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

您的操作系統可能不會觸發keyReleased事件,而只會keyTyped keyPressedkeyTyped事件或其他組合,因此請先檢查該事件。 您可能只需要檢查keyTyped事件而不是keyReleased ,您將完成它。

簡短回答:

使用位掩碼或數組來跟蹤當前處於“已按下”狀態的鍵,然后使用那些值來觸發事件。 也就是說,不要直接使用Swing事件來觸發應用程序中的響應 - 您需要一個基本上存儲鍵盤狀態的額外層,並從該狀態開始執行相關操作。

還有一些方法可用( 參見本教程結尾 - “isAltDown”,“isCtrlDown”等 )來檢查當您收到按下“Space”鍵之類的事件時是否按下了修改鍵。

答案很長:

你按下並釋放按鍵時會觸發事件是正確的。 它必須以這種方式工作,以便您可以支持應該單獨處理這些事件的應用程序,而不是一起處理。 一個例子(雖然這不是唯一一個)是PC上的視頻游戲,你可能會同時按下多個字母/修改鍵(例如, A向左移動, W向前移動)游戲必須對待這兩個事件作為不同的輸入,而不是復合輸入,導致你的前進 - 左移動。

所以,你基本上想做的事情,如果你需要處理復合輸入,就有一個簡單的應用程序需要響應的動作數組,以及它們相關的鍵綁定(無論是單鍵還是多鍵都不重要) )。 當按下某個鍵時,你基本上會打開該鍵的標志,表示它當前處於“按下”狀態,並在釋放時清除該標志。

然后,要觸發您的事件,您只需檢查所有按下的鍵(通過檢查哪些鍵“標志”處於活動狀態),如果按下特定事件的鍵組合,則觸發事件。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM