Java - 是否可以在不使用监听器的情况下检测按键是否被按下?

6
我需要能够在我的特定操作期间检测某个键(例如CTRL)是否被按下。我无法访问键监听器或鼠标事件。我希望有一个类有一个像“boolean isKeyPressed(keycode)”这样的方法。
有人知道Java中是否有这样的方法吗?
背景:我正在尝试覆盖组件的默认拖放行为。根据DropTargetDragEvent的Javadoc,默认情况下,如果没有按键修饰符被按下,则它会在组件的支持操作列表中查找移动,然后是复制和链接,找到第一个后停止。
在我的应用程序中,我们支持复制和链接。根据Javadoc,如果没有按下CTRL键,则默认操作是复制。我们希望用户能够指定默认操作(允许他们设置最常用的操作),然后使用修改键强制执行特定操作。
如果我能检测到按键状态,那么我就可以强制执行此操作,但我看不到任何其他更改默认操作的方法。
谢谢,Brian

5
为什么你无法访问侦听器?你不能自己创建一个吗?你正在使用哪个GUI框架? - Noel M
Noel - 请看我的对Erick Robertson帖子的评论。 - BrianHobbs
4个回答

5

MouseEvent.getModifiers() 方法会返回一个位图,其中包含在生成 MouseEvent 时按下的修改键。或者,您可以使用 MouseEvent.isControlDown() 来检查特定的 CTRL 键。


我同意在理想的情况下,键盘监听器可能是最好的选择。但是,在我的观点中,对于我的场景,这种方法存在一些问题:我应该将监听器附加到什么上面?我的应用程序在UI方面非常复杂,并且还可以通过插件进行定制。我尝试将监听器附加到事件线程,但这最终会处理所有键盘事件,因此可能会影响其他地方的性能。同样,应用程序的可扩展性意味着我不一定有办法检测拖动的开始,因此我无法有选择性地打开监听器。 - BrianHobbs
我刚刚在尝试使用键盘监听器,结果发现当鼠标按键被按下时,键盘事件不会被触发(我正在处理拖放操作),因此这就排除了使用键盘监听器的可能性。我想我可以尝试使用全局鼠标监听器并检查修饰键的状态,但这似乎对于这个问题来说有些过度设计了。 - BrianHobbs
我更新了我的回复 - 你可以检查每次鼠标移动或拖动时生成的MouseEvent。 - Erick Robertson

1
这可能是一种不太规范的方法。但它允许您“记录”关键事件,然后查询它们。
//register this somewhere in the startup of your application
KeyboardFocusManager mgr = KeyboardFocusManager.getCurrentKeyboardFocusManager();
    mgr.addKeyEventDispatcher(KeyEventRecorder.getInstance());

//then can query events later
    KeyEvent keyEvt = KeyEventRecorder.getLastEvent();
    if( keyEvt != null && keyEvt.getKeyCode() == KeyEvent.VK_CONTROL && keyEvt.getID() == KeyEvent.KEY_PRESSED )
      //do something..

    private class KeyEventRecorder implements KeyEventDispatcher
    {
        private static KeyEvent lastEvent;
        private static KeyEventRecorder myInstance;

        private KeyEventRecorder()
        {
            super();
        }

        public static synchronized KeyEventRecorder getInstance()
        {
            if( myInstance == null )
                myInstance = new KeyEventRecorder();
            return myInstance;
        }

        /**
         *  retrieve the last KeyEvent dispatched to this KeyEventDispatcher
         */
        public static KeyEvent getLastEvent()
        {
            return lastEvent;
        }//method

        @Override
        public boolean dispatchKeyEvent(KeyEvent e)
        {
            lastEvent = e;
            //return false to let KeyboardFocusManager redistribute the event elsewhere
            return false;
        }//method
    }//class

0
即使有这样的方法,你想用它做什么?在无限循环中调用它,希望它在某个时刻返回 true 吗?我认为在这种情况下,基于事件/监听器的机制更加适合。

1
不是无限循环。只在特定操作(拖放期间回调)期间按需调用。 - BrianHobbs

0

我认为你的方法不对。你想要做的是在拖动开始时改变操作,而不是在放下时改变。有办法在启动时更改操作,包括在“无修饰符”情况下查询用户首选项。可能需要更改DropTargetDragEvent的调用方式。


我同意 - 但我还没有找到如何在代码中设置“无修饰符”情况的方法 - javadocs(请参见我原始帖子中的链接)表明复制优先于链接。如果您有任何关于如何做到这一点的建议,那将不胜感激。 - BrianHobbs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接