【问题标题】:How to receive key events during a drag&drop?如何在拖放期间接收关键事件?
【发布时间】:2009-12-16 14:30:47
【问题描述】:

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

我正在拖动一个实现 KeyListener 的 JComponent 子类,并在 DragSourceListener 的 dragEnter 方法中请求焦点,但我的假设是焦点随后会从它身上移开。

现在,谁获得了焦点,我怎样才能把它带回我的 JComponent。还是有更适合 dnd 的不同方法?

提前谢谢你。

更新

要完成这项工作需要大量代码,所以我只会发布一些 sn-ps 来向您展示我正在尝试做的事情:

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

【问题讨论】:

  • 可以放上你正在使用的代码吗?你在使用任何 IDE 吗?
  • 我尝试输入尽可能多的代码,因为我认为这会有所帮助。我不认为这有什么区别,但我使用的是没有任何插件的 Eclipse Ganymede。顺便提一句。这不是一个小程序,而是一个标准的桌面应用程序。

标签: java swing focus drag-and-drop


【解决方案1】:

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

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

+ 我的重点。

基本上我们使用类似的代码在 KeyEvents 到达具有焦点的组件之前拦截它们。

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

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 来确定在拖放过程中谁最终获得了焦点?

无论如何,我希望这能给你一些新的尝试。

【讨论】:

  • 这看起来很有希望,并且到目前为止效果很好。我还没有时间解决启用/禁用部分,但这似乎并不是很复杂。只要我有时间尝试一下,我就会接受你的回答。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-15
  • 2013-10-21
  • 2020-03-01
  • 2016-12-01
相关资源
最近更新 更多