2012-08-08 54 views
2

我在這裏需要一些幫助。我有一個阻塞函數在我的主線程中等待用戶點擊「Enter」。然後,當用戶點擊輸入時,按下按鍵的事件應該會觸發,這將解除阻止功能。但是,當程序遇到阻塞函數時,它會凍結並且不會註冊按鍵事件。我有一個Java線程和KeyEvent的問題?

所以,我的問題是,是一個可運行的事件,只要用戶點擊輸入,它就會添加到線程中?如果是這樣,我的代碼應該工作,對吧?如果情況並非如此,並且每個事件都不是一個單獨的線程,那麼是否有人能夠啓發我如何解決我的問題? 我的阻擋功能:

public String getInput() { 
    synchronized(waitObject) { 
     try { 
      System.out.println("waiting"); 
      waitObject.wait(); // throws exception, cba to add it here 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
    return(myString); 
} 

我的KeyListener代碼:

public void keyPressed(KeyEvent e) { 
    System.out.println("key pressed"); 
    char c = e.getKeyChar(); 
    if (c == e.VK_ENTER) { 
     System.out.println("Enter pressed"); 
     synchronized(waitObject) { 
      waitObject.notifyAll(); 
     } 
    } 
} 

和功能獲取輸入:

public class Listener implements KeyListener { 
    public void keyPressed(KeyEvent e) { 
     if (e.getKeyCode() == KeyEvent.VK_F2) { 
      System.out.println(getCommand()); 
     } 

    } 
    public void keyReleased(KeyEvent e) { 

    } 
    public void keyTyped(KeyEvent e) { 

    } 
} 

private String getCommand() { 
    System.out.println("getting command"); 
    CommandField command = new CommandField((JFrame)(this)); 
    command.setPreferredSize(new Dimension(getWidth(), 30)); 
    m_panel.add(command, BorderLayout.NORTH); 
    validate(); 
    command.requestFocus(); 
    System.out.println(command.getInput()); 

    return null; 
} 

而這個功能是從另一個KeyListener的叫

+3

您可以發佈您的代碼的相關作品? – Keppil 2012-08-08 13:37:32

+2

AWT使用[*事件調度線程*](http://en.wikipedia.org/wiki/Event_dispatching_thread)。如果你佔用這個線程,它將無法工作 - 而且你不會收到你的'KeyEvent'。 – oldrinb 2012-08-08 13:41:05

+0

@Keppil添加了相關代碼 – AlphaUserGuru 2012-08-08 14:09:50

回答

2

OK,getCommand()在事件線程上調用,然後在同一個線程上調用getInput(),然後在事件線程上調用Object#wait(),所以是的,你正在綁定事件線程並有效地凍結你的程序。需要這種

無時,如果使用事件驅動編程的概念,你的代碼更簡單的解決方法是可行的。您不想在Swing GUI中調用wait(),並且您的情況不需要調用它,而是想要根據其狀態更改程序對輸入的響應方式。如果您告訴我們更多關於您試圖引發的確切行爲的信息,我們可以幫助您找到更好的解決方案。

編輯
考慮使用的JOptionPane或一個模式的JDialog顯示一個「堵」窗口,直到對話框已經處理了該停止主程序。

+0

嗯,我不知道我應該擴展什麼 - 我想要的行爲:CommandField(我的版本的擴展JPanel的文本字段)應該這樣做:用戶在JFrame中按下一個鍵,命令字段彈出。用戶可以輸入一個字符串,然後單擊enter。一直等待阻塞函數commandfield.getInput()的JFrame將不會等待並獲取輸入。 – AlphaUserGuru 2012-08-08 14:27:16

+0

@ user1493275:爲什麼不簡單地爲此使用JOptionPane?或者一個模態JDialog?警告:你應該避免使用KeyListeners,因爲它們對焦點非常敏感。如果正在偵聽的組件沒有焦點,則KeyListener將不起作用。更好地使用密鑰綁定。 – 2012-08-08 14:31:21

+0

將研究這一點。感謝您的幫助! – AlphaUserGuru 2012-08-08 14:35:24

2

ImageApp開始,我在構造函數中添加了以下key bindingshow()彈出菜單當按時輸入鍵。您可以更改任意位置以適合您的使用。

this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "showPopup"); 
this.getActionMap().put("showPopup", new AbstractAction("showPopup") { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     popup.show(ImageApp.this, 42, 42); 
    } 
}); 

附錄:彈出一個模態輸入對話框,所以是這樣的:

this.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "dialog"); 
this.getActionMap().put("dialog", new AbstractAction("dialog") { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     String value = JOptionPane.showInputDialog("What?"); 
     System.out.println(value); 
    } 
});