如何在拖放过程中接收关键事件?

时间:2009-12-16 14:30:48

标签: java swing focus drag-and-drop

我目前正在尝试在拖放过程中接收关键事件,但在我看来,拖动时焦点被移除,因此我无法收听任何关键事件。

我正在拖动一个实现KeyListener的JComponent子类,并在DragSourceListener的dragEnter方法中请求焦点,但我的假设是之后焦点被从中删除。

现在,谁有了焦点,我怎么能把它带回我的JComponent。或者是否有更适合dnd的不同方法?

提前谢谢。

更新

要完成这项工作需要很多代码,所以我只会发布一些片段来向您展示我正在尝试做的事情:

public class Stone extends JComponent implements Serializable, KeyListener {

    public Stone(...) {

        //...

        setFocusable(true);
        addKeyListener(this);

        this.dragSource = DragSource.getDefaultDragSource();
        this.dgListener = new StoneDGListener();
        this.dsListener = new StoneDSListener();

        this.dragSource.createDefaultDragGestureRecognizer(
            this, 
            DnDConstants.ACTION_MOVE, 
            this.dgListener
        );

        //...

    }

    //...

    public void keyPressed(KeyEvent e) {
        System.out.println("Stone: "+e.getKeyCode());
    }

    //...

    public class StoneDSListener implements DragSourceListener, Serializable {

        //...       

        @Override
        public void dragEnter(DragSourceDragEvent dsde) {
            //...   
            Stone.this.requestFocus();
            addKeyListener(Stone.this);
        }

        //...
    }
}

在我拖动Stone组件之前,我的JPanel具有焦点,因此它会接收我正在按下的任何键。 在拖动过程中我无法听到任何按下的键(所以我不知道谁有焦点)即使我在dragEnter()中请求它并且在我释放Stone任何键之后事件将发送到Stone

对于这个问题可能并不重要,但要说明我在这里做的是截图:

image showing the "drag" http://img685.imageshack.us/img685/1884/pico.png (这里我将Stone从下面的集合拖到顶部的游戏区域。在这种状态下,我不知道如何找出按下的键。我需要弄清楚这一点,以便能够旋转Stone

1 个答案:

答案 0 :(得分:3)

在拖放过程中不确定谁有焦点。但是,对您的问题的另一种解决方案是为您的Stone类添加KeyEventDispatcherKeyboardFocusManager。来自JavaDoc:

  

KeyboardFocusManager既是客户端代码的集中位置,可以查询焦点所有者并启动焦点更改, 事件调度程序 FocusEvents,与焦点相关的WindowEvents,以及 KeyEvents +

+我的重点。

基本上我们使用类似的代码拦截KeyEvent,然后才能点击具有焦点的Component。

只是对你的特定拖放上下文进行了快速测试,它似乎正常工作(只要你的应用程序在操作系统中有焦点)。基本上是:

Public Stone(...) {
    // ...

    KeyboardFocusManager fm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
    fm.addKeyEventDispatcher(
        new KeyEventDispatcher() {
            public boolean dispatchKeyEvent(KeyEvent e) {
                System.out.println("Key Press: " + e.getKeyChar());
                return false;
            }            
        } 
    );

   // ... 
}

当用户不再拖放时,您需要做一些关于启用和禁用的工作,因为我的测试当前一直在打印。

我也想知道是否可以使用KeyboardFocusManager来确定在拖放过程中谁最终得到了焦点?

无论如何,我希望这会给你一些新想法。