2007/11/30

修改keylistener的input/action map

前兩天寫聊天室程式的時候, 想模仿MSN,
只要使用者按enter key,便可把輸入區的文字,寫入outputStream,並清空輸入區的文字。


文字輸入區我是用JScrolPane包JTextArea,
並在JTextArea中的enter key事件驅動時,
呼叫JTextArea的setText("")來清空輸入區的文字。


結果發生一件詭異的事,
那就是雖然輸入區的文字是如期清空了,
但游標卻總是停在第二行的開頭,而不是停在首行的開頭。
我試了在keyPressed()裡去改變最後JTextArea的caret位置,如setCaretPosition()等...
但就是無法把caret移到首行的開頭。


最後終於在google上找到解法。

來源網址http://en.allexperts.com/q/Java-1046/JTextArea-caret-postion.htm

Question

Sir, I was making one application which has 2 JTextArea's and 1 button.
When i enter some text in textArea-2 and press 'Enter Key', it should transefer the text to textArea-1 and must empty the textArea-2 and now the focus should be present on the button(that is the caret should not be present in textArea-2).
I had written code for Keylistener and the text is being transeferred correctly if 'Enter Key' was pressed, but textArea-2 is not being emptied, it is still having the caret placed in a new line. So, each time i'm pressing 'Back space' key to make the caret shift to the first line.
Can u tell how to make the textArea-2 empty and shift the focus to the button when 'Enter Key' is pressed?

Answer

The problem is that when you clear the text the enter key is still being processed by the text area, so a new line is being created. You might consider using a JTextField to handle single line input.

You should be using the input/action map instead of keylisteners to handle this.


E.g.

InputMap inputMap = textArea.getInputMap();
ActionMap actionMap = textArea.getActionMap();
Object transferTextActionKey = "TRANSFER_TEXT";

inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),transferTextActionKey);

actionMap.put(transferTextActionKey,new AbstractAction() {
 public void actionPeformed(ActionEvent e) {
  textField2.setText(textField.getText());
  textField.setText("");
  textField2.requestFocus();
 }
});


Doing this will replace the existing binding of Enter of JTextArea (which is to call replaceSelection("\n"))

主要的問題出在enter key事件驅動後,雖然呼叫了setText("")來清空輸入區的文字,
但enter key本身卻在事件結束後,會塞入JTextArea,所以會空出一行。


解決的辦法,便是將JTextArea的Enter key action,由原本的"\n"改成setText(""),
這麼一來,使用者在JTextArea按下Enter key時,
便會將輸入區的文字清空, 但不會塞入一條空白行,


因為原本的action - "\n"被替換掉了。
而keyPressed()只需處理將文字寫入outputStream即可(原先需做輸入區文字的清空)。


No comments:

Post a Comment