2013-04-03 86 views
1

我正在研究一個JTextPane,它幾乎和stackoverflow上的標籤輸入字段一樣。爲此,只要用戶點擊輸入,標籤或空格,我就會將文本轉換爲組件。當然,我不希望任何這些字符實際上被輸入到文本窗格。我發現這個解決方案,SSCCE:將某些字符/鍵的輸入重新映射到JTextComponent的最佳方法?

import java.awt.Color; 
import java.awt.event.ActionEvent; 

import javax.swing.AbstractAction; 
import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JTextPane; 
import javax.swing.KeyStroke; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.Element; 
import javax.swing.text.StyledDocument; 

@SuppressWarnings("serial") 
public class TagTextPane extends JTextPane { 

    public TagTextPane() { 
     this.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "finalizeTag"); 
     this.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "finalizeTag"); 
     this.getInputMap().put(KeyStroke.getKeyStroke("TAB"), "focusNext"); 
     this.getActionMap().put("focusNext", new AbstractAction() { 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       finalizeTag(); 
       transferFocus(); 
      } 
     }); 
     this.getActionMap().put("finalizeTag", new AbstractAction() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       finalizeTag(); 
      } 
     }); 
    } 

    private void finalizeTag() { 
     StyledDocument doc = (StyledDocument) getDocument(); 
     Element element = doc.getCharacterElement(getCaretPosition() - 1); 
     int start = element.getStartOffset(); 
     int len = element.getEndOffset() - start; 
     String tag = ""; 
     try { 
      tag = this.getDocument().getText(start, len); 
     } catch (BadLocationException e) { 
     } 
     this.setSelectionStart(start); 
     this.setSelectionEnd(start + len); 
     JLabel label = new JLabel(tag); 
     label.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
     this.insertComponent(label);   
    } 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("TagTextPaneTest"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     TagTextPane tPane = new TagTextPane(); 
     frame.setSize(400, 100); 
     frame.getContentPane().add(tPane); 
     frame.setVisible(true); 
    } 
} 

擊中「標籤」通常會導致要插入一個製表符,打「回車」,通常將導致進入一個換行符,以及打擊「空間」導致空間被輸入。奇怪的是,我的代碼停止輸入換行符和製表符,但仍允許在執行預期操作時正常輸入空格。

  1. 爲什麼這種方法對這些密鑰的行爲不同?

  2. 如何阻止輸入空間? (也許我想稍後將此行爲擴展爲逗號等等。)

  3. 如何最佳地控制JTextComponent中某些字符和擊鍵的行爲?我見過this,其中建議使用KeyListener,但我也看到this,Rob Camick指出,爲什麼不應使用KeyListener。所以我應該使用DocumentFilter還是在輪子上打蝴蝶?

  4. 這甚至是建立這種標籤輸入字段的最佳方式嗎?

+0

參見[*如何使用按鍵綁定*](http://docs.oracle.com/javase/tutorial/uiswing/misc /keybinding.html)有關特殊操作名稱「none」。 – trashgod

+0

@trashgod我已經閱讀過,但是我的解釋是,如果我不想讓密鑰導致任何其他行爲(這是我想要的),那麼我就不能使用「無」行爲。但重點是我沒有使用「無」操作,我已經使用了正確命名的操作。 – nfs

+0

哎呀,我雖然'SPACE'有約束力。也許使用一個'DocumentListener'? – trashgod

回答

2
this.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "finalizeTag"); 

這是處理的空格字符keyPressed事件。

你要處理的空格字符的事件的keyTyped:

this.getInputMap().put(KeyStroke.getKeyStroke(' '), "finalizeTag"); 
+0

啊哈,「如果輸入','按'或'釋放'沒有指定,則按'按'。」 – trashgod

+0

這回答我的問題沒有2和3,但它回答沒有1?重點是,我以同樣的方式(假設'按')註冊所有三個鍵的事件,但它們的行爲不同,因爲實際上沒有鍵入選項卡和換行符。我可以理解,如果新行的工作方式不同,因爲它在不同的系統上不是同一個字符,但標籤應該是,對吧? – nfs

+0

@SheridanVespo,所有的鍵都表現相同,也就是說,你的finalizeTag動作被調用。當您按下空格鍵時,這也會生成一個keyTyped事件,該事件實際上是在執行完finalizeTag動作之後將「」添加到文檔的事件。 Tab和Enter鍵不會生成keyTyped事件,因此沒有任何內容添加到文檔中。 – camickr

相關問題