【问题标题】:Removing KeyEvents from an ArrayList从 ArrayList 中删除 KeyEvent
【发布时间】:2014-05-14 20:33:54
【问题描述】:

问题:

我有一个实现KeyListener 的类来收集按键列表。然后将该列表委托给KeyListener 的实例进行处理。每次释放密钥时,都必须将其从列表中删除。

我的问题是它们没有从列表中删除,因为按下时我存储在列表中的KeyEvent 与释放键时生成的KeyEvent 不同。这会导致没有任何 KeyEvent 被删除,因此它们会累积。

我必须进行哪些更改以确保我可以删除 KeyEvent,而只知道同一密钥的不同 KeyEvent(删除方法检查 .equals())?


代码:

KeyListener subject;
    ArrayList<KeyEvent> pressed = new ArrayList<KeyEvent>();

    public MultiKeyListener(KeyListener subject) {
        this.subject = subject;
    }

    @Override
    public void keyPressed(KeyEvent k) {
        pressed.add(k);
        if (subject != null && pressed.size() > 0) {
            for (int i = 0; i < pressed.size(); i++) {
                subject.keyPressed(pressed.get(i));
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent k) {
        pressed.remove(k);
        if (subject != null && pressed.size() > 0) {
            for (int i = 0; i < pressed.size(); i++) {
                subject.keyPressed(pressed.get(i));
            }
        }
    }

    @Override
    public void keyTyped(KeyEvent k) {

    }

【问题讨论】:

  • 您能否再解释一下为什么要将事件传递给另一个按键侦听器,以及为什么在按键被按下和释放时都发送所有按键事件?
  • @KevinSheehan 目的是让我可以解耦 KeyEvents 的处理,这样我就不需要在每次编写新类时都编写新的MultiKeyListener。相反,我编写了一个 KeyListener 并将其传递给 MultiKeyListener。
  • 抱歉,我有点困惑,为什么您不能跟踪所有被按下的键,然后只在需要的地方进行检查?您不会让不同的侦听器接收不同的键输入吗?
  • @KevinSheehan 目前,我正在使用 KeyListeners 来移动玩家,每个玩家都提供自己的 KeyListener。每次我需要新的行为/类(播放器控制、菜单等)时,编写 MultiKeyListener 似乎是违反直觉的。最简单的方法是为每个编写一个简单的 KeyListener,并将它们添加到窗口的 MultiKeyListener。

标签: java arraylist keylistener keyevent


【解决方案1】:

在 KeyEvent 周围使用包装器。

public class KeyEventWrapper
 {
     private KeyEvent keyEvent;

     public KeyEventWrapper(KeyEvent keyEvent)
      {
         this.keyEvent = keyEvent;
      }  

     public KeyEvent getKeyEvent()
      {
         return keyEvent;
      }

     public boolean equals(Object object)
      {
          if(object instanceof KeyEventWrapper)
            {
                KeyEventWrapper wrapper = (KeyEventWrapper) (object);
                KeyEvent k = wrapper.getKeyEvent();

                return (this.keyEvent.getKeyCode() == k.getKeyCode());
            } 
          return false;
      }

     public int hashCode()
       {
           return this.keyEvent.getKeyCode();
       }
 }

现在,您可以使用此包装对象的 ArrayList 来代替 KeyEvent。

ArrayList<KeyEventWrapper> pressed = new ArrayList<KeyEventWrapper>();
... 
pressed.add(new (KeyEventWrapper(k));
...
pressed.remove(new (KeyEventWrapper(k));

【讨论】:

    【解决方案2】:

    您可能希望存储按下的键,而不是 KeyEvent 本身。每次按下、键入或释放键时都会发生一个新事件。您要跟踪的是KeyCodeKeyChar

    编辑:只是另一个建议,您可能需要考虑使用Set 而不是List 来跟踪已按下的键。一个键实际上不能按多次。

    【讨论】:

    • 我正在委托另一个 KeyListener;我必须将 KeyEvent 传递给它。我应该删除KeyListener subject 以允许此功能吗?
    • 我最初没有投票,因为我不太明白您的答案如何适用。您关于使用 Set 的建议很有见地,但不符合我的需求。虽然你的回答对我没有用,但这是非常中肯的建议。
    【解决方案3】:

    我想说你应该迭代 pressed List 从末尾到开头,并删除那里第一次出现的具有相同 KeyCode 的 KeyEvent。像这样的:

    @Override
        public void keyReleased(KeyEvent k) {
            for (int i=pressed.size()-1;i>=0;i--) {
                 if (pressed.get(i).getKeyCode()==k.getKeyCode()) {
                     pressed.remove(i);
                     break;
                 }
            }
        ......
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-29
      • 2013-02-24
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多