Swing程序的模拟键盘事件

本文探讨了Java中FRAME窗口添加组件后不响应键盘事件的问题,并详细解答了如何模拟键盘事件及解决keyPressed与keyReleased事件触发异常的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

第一个问题: 
FRAME 窗口添加了组件后,为什么不响应 KEYPressed 事件??? 

第二个问题: 
keyPress 与 keyRelease 事件一般成对触发,为什么在 调用了 JOptionPane.showMessageDialog() 方法后, keyReleased 事件不触发了?? 

第三个问题: 
怎么样模拟键盘事件,让程序返回桌面,不使用 Runtime.exec() 的方式,使用模拟键盘事件的方式。 

下面是我的测试代码: 

Java code



Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

import java.util.*;



public class  FrameTest extends JFrame implements ActionListener

{



    public KeyAdapter kd = new KeyAdapter(){

        public void keyPressed(KeyEvent e)

        {

                JOptionPane.showMessageDialog(null,"使用了键盘!----------");

                System.out.println("使用了键盘!----------");

        }

        public void keyReleased(KeyEvent e)

        {

                //JOptionPane.showMessageDialog(null,"释放了键盘!");

                System.out.println("释放了键盘!----------");



        }

    };



    public FrameTest()

    {

        Container cp = getContentPane();

        cp.setLayout(new FlowLayout());

        JButton jb = new JButton("Click");

        jb.addActionListener(this);

        //cp.add(jb);



        

        JTextField tf = new JTextField(10);

        //cp.add(tf);

        tf.addKeyListener(kd);

        this.addKeyListener(kd);

        this.setSize(300,180);

        this.setTitle("FrameTest");

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        show();

        



        // 下面注释的代码,想模拟 'windows D ' 事件,但没有成功

        /*

        KeyEvent ke = new KeyEvent(this,1100,new Date().getTime(),KeyEvent.VK_WINDOWS,KeyEvent.VK_D,'D');

        this.kd.keyPressed(ke);

        KeyEvent kup = new KeyEvent(this,1100,new Date().getTime(),KeyEvent.VK_WINDOWS,KeyEvent.VK_D,'D');

        this.kd.keyReleased(kup);

        */



    }



    public void actionPerformed(ActionEvent event)

    {



    }



    public static void main(String[] args) 

    {

        FrameTest ft = new FrameTest();

    }

}






网友回复:刚试了一下jdk6可以模拟
网友回复:增加了组件,比如你程序里的cp.add(jb),jb默认是获得了焦点的,你的键盘监听只是对JFrame,所以需要取消jb上的焦点,jb.setFocusable(false);
网友回复:第一个问题: 
frame处于最底下,当有东西放到他上面时,就会把他给覆盖掉了,从而使他frame得不到焦点,也就触发不了Key事件 

第二个问题 
JOptionPane.showMessageDialog是线程同步的,当弹出dialog时,焦点已转到dialog,父窗口已失去焦点,也就是说当按下键时随着dialog的弹出就已经失去了焦点,所以也就不存在键的释放 

第三个问题 
不太明白你所要问的意思?
网友回复:第二个我估计是由于MessageDialog弹出太快了,马上获得了焦点,时候released的监听被阻断了,可以人工加一个线程,然后延迟MessageDialog弹出的时间,比如延迟0.1秒,让released有时间去监听到 

修改如下: 
Java code



Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





public KeyAdapter kd = new KeyAdapter() {

    public void keyPressed(KeyEvent e) {

        new Thread(new Runnable() {

            @Override

            public void run() {

                try {

                    Thread.sleep(100); // 这里模拟稍微等候一下,然监听可以到released

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

                JOptionPane.showMessageDialog(null, "使用了键盘!----------");



            }

        }).start();

        System.out.println("使用了键盘!----------");

    }



    public void keyReleased(KeyEvent e) {

        // JOptionPane.showMessageDialog(null,"释放了键盘!");

        System.out.println("释放了键盘!----------");



    }

};




网友回复:第三个问题的意思: 
当窗口显示的时候,模拟WINDOWS 的键盘事件: windows D ,就是返回桌面组合键。 


关于第一个问题:我还是比较认同 (whatisjava_open )的回答,毕竟通过设置setFocusable(false)的方法不是很可取,当窗口上组件比较多的时候,就不是很好的解决方案了。 


网友回复:第三个问题: 
如果你只是想实现 windows D ,就返回桌面组合键 这样的功能的话,那你不用做什么,这样的功能是已经有的,因为这是windows的功能 

如果你是想实现一个全局键盘监听的话,那么可以这样做: 
把FrameTest再实现AWTEventListener这个接口,你会得到一个接口方法: 
public void eventDispatched(AWTEvent event) { 

再构造子里面加这两行代码 
Toolkit toolkit = Toolkit.getDefaultToolkit(); 
toolkit.addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK); 

在eventDispatched方法里面: 
public void eventDispatched(AWTEvent event) { 
KeyEvent ke = (KeyEvent)event; 

System.out.println("做你想做的 ..."); 


网友回复:

第三个问题的意思: 
当窗口显示的时候,模拟WINDOWS 的键盘事件: windows D ,就是返回桌面组合键。 


关于第一个问题:我还是比较认同 (whatisjava_open )的回答,毕竟通过设置setFocusable(false)的方法不是很可取,当窗口上组件比较多的时候,就不是很好的解决方案了。 

win d这个不用模拟吧,直接就返回桌面了啊?如果是鼠标点击一个什么按钮,触发win d的键盘事件还能明白。 
jb.setFocusable(false)只是一个说法,就这个例子而言还可以用this.setFocusable(true);就可以了,让JFrame获得焦点。
网友回复:那好,解决最主要的问题:通过按钮来触发win d的键盘事件 
Java code



Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





import javax.swing.*;

import java.awt.event.*;

import java.awt.*;

import java.util.*;



public class  FrameTest extends JFrame implements ActionListener

{



    public KeyAdapter kd = new KeyAdapter(){

        public void keyPressed(KeyEvent e)

        {

                System.out.println("使用了键盘!----------");

        }

        public void keyReleased(KeyEvent e)

        {

                System.out.println("释放了键盘!----------");



        }

    };



    public FrameTest()

    {

        Container cp = getContentPane();

        cp.setLayout(new FlowLayout());

        JButton jb = new JButton("Click");

        jb.addActionListener(this);

        cp.add(jb);



        

        JTextField tf = new JTextField(10);

        cp.add(tf);



        this.setFocusable(true);

        tf.addKeyListener(kd);

        this.addKeyListener(kd);

        this.setSize(300,180);

        this.setTitle("FrameTest");

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        show();

        

        

        KeyEvent ke = new KeyEvent(this,1100,new Date().getTime(),0,KeyEvent.VK_WINDOWS,(char)KeyEvent.VK_WINDOWS);

        this.kd.keyPressed(ke);



        ke = new KeyEvent(this,1100,new Date().getTime(),0,KeyEvent.VK_D,'D');

        this.kd.keyPressed(ke);



    }



    public void actionPerformed(ActionEvent event)

    {

        //JOptionPane.showMessageDialog(null,"按下了按钮!----------");

        KeyEvent ke = new KeyEvent(this,1100,new Date().getTime(),KeyEvent.VK_WINDOWS,KeyEvent.VK_D,'D');

        this.kd.keyPressed(ke);

        KeyEvent kup = new KeyEvent(this,1100,new Date().getTime(),KeyEvent.VK_WINDOWS,KeyEvent.VK_D,'D');

        this.kd.keyReleased(kup);

    }



    public static void main(String[] args) 

    {

        FrameTest ft = new FrameTest();

    }

}




网友回复:按照更新后的代码,好想还是无法返回桌面?
网友回复:鼠标点击一个什么按钮,触发win d的键盘事件 的问题,有人知道怎么解决吗?
网友回复:难道无法结贴了不成?
网友回复:你要实现win D键的效果,给你个代码: 
Java code



Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/





import java.awt.Robot;

import java.awt.event.KeyEvent;



public class Test{

    public static void main(String args[])throws Exception{

        Robot r = new Robot();

        r.keyPress(KeyEvent.VK_WINDOWS);

        r.keyPress(KeyEvent.VK_D);

        //按下了要释放,要不然将会出现奇怪的问题~嘿嘿

        r.keyRelease(KeyEvent.VK_WINDOWS);

        r.keyRelease(KeyEvent.VK_D);

        

    }

}




你只要把代码放到合适的地方即可,这样写虽然能在windows下使用,但是其他系统就不行了 

 

 

 

另外:

你自己用了是不好使,说明你会做,可能事件捕获不到。
按我方法试试,应该自己能做出来的。
在现在的JDK中,键盘事件只有具有焦点的组件才能捕获。因此,你应该把你所有的键盘事件都绑到同一个组件上。而且要保持此组件有焦点。
计算器上有很多按钮,一点这些按钮你捕获事件的组件就失去焦点了,解决这个问题的方法是你在这些按钮的的mouseReleased事件中,加上一句指定你捕获器组件强制获取焦点。这样就能保持捕获器永远有焦点了。
你的捕获器.requestFocusInWindow() 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值