2014-10-31 102 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