Swing程序的模拟键盘事件

来源:互联网 发布:win10 ubuntu安装教程 编辑:程序博客网 时间:2024/06/07 18:42

 

第一个问题: 
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()