2014-10-31 86 views
2

嘿我试图让控制台打印出“持有”,当一个键被举行。我正在使用小程序 ,因为此代码是要测试小程序中的密钥。如果任何具有良好Java知识的人都可以向我解释发生了什么事情,我将非常感激。keyListener和线程不工作

我敢肯定,问题可能与线程有关。

public class appletkeytest extends Applet implements KeyListener, Runnable { 

    boolean held; 

    public void init(){ 
     addKeyListener(this); 
     Thread t = new Thread(this); 
     t.start(); 
    } 

    public void keyTyped(KeyEvent e) { 
    } 

    public void keyPressed(KeyEvent e) { 
     held = true; 
     System.out.println(held); 
    } 

    public void keyReleased(KeyEvent e) { 
     held = false; 
     System.out.println(held); 
    } 

    public void run() { 
     System.out.println(held); 

     while(held){ 
      System.out.println("holding"); 
     } 
    } 
} 
+1

'while(held)'应该是'while(true)',你可能需要在附加条件下打破循环。这里发生了什么,甚至在你按下键之前已经执行了'run'方法。 – 2014-10-31 22:40:10

回答

1

首先,我建议将held定义为volatile。

其次,由于您从init()方法启动线程,它将在您按下键之前开始运行,并因此立即完成。

我会离开init这样的:

public void init() { 
    addKeyListener(this); 
} 

并更改keyPressed监听器:

public void keyPressed(KeyEvent e) { 
    boolean wasHeld = held; 
    held = true; 
    System.out.println(held); 
    if (!wasHeld) { 
     Thread t = new Thread(this); 
     t.start(); 
    } 
} 

wasHeld变量背后的原因是,当你按住一个键,它实际上发送多个keyPressed事件直到它被释放。如果你为每一个按钮创建了一个线程,你将在一次按键过程中创建多个线程,所有这些线程都会忙着写入控制台。

所以,只有在这是第一次为此特定按键发送keyPressed事件时,您才想创建线程。在释放前一个键之后再次按下某个键时,将创建一个新线程。

+0

我会在'init'方法中添加'requestFocus()'......我不知道这是否与IDE不同,或者其他什么不同,但是我必须先点击applet才能让它聚焦,这样事情就可以发生;补充说,会自动给它的焦点。 – TNT 2014-10-31 23:16:46

+0

@TNT - 对我不起作用。它可以是Eclipse或MacOS X,但在'init()'Applet不可见,因此'requestFocus()'失败。 – RealSkeptic 2014-10-31 23:32:20

+0

可能是。我现在正在使用MacOS X. – TNT 2014-10-31 23:40:32