2014-04-08 38 views
1

我使用JTextArea其中使用雙擊我可以在任何地方選擇單詞,但我不想啓用編輯。這意味着文本只能在文本區域的末尾輸入,而不能在兩者之間的任何位置輸入。JTextArea - 啓用僅在文檔末尾編輯

我曾與鼠標偵聽試圖象下面這樣:

@Override 
public void mouseClicked(MouseEvent me) { 
     if(SwingUtilities.isLeftMouseButton(me)){ 
     System.err.println("clicked"); 
     int pos = textArea.getCaretPosition(); 
     if(pos < textArea.getDocument().getLength()){ 
      textArea.setCaretPosition(textArea.getDocument().getLength()); 
     } 
    } 
    } 

這使得雙擊不能選擇單詞。我明白這是因爲插入符的位置移動到了最後。但我怎麼能做到這一點?

+0

爲了更好地幫助越早,張貼[MCVE]( http://stackoverflow.com/help/mcve)(最小完整和可驗證示例)。 –

+1

我可以在將來看到一個'DocumentFilter' ... – MadProgrammer

+0

*「只能在文本區域的末尾輸入文本,而不能在兩者之間的任何位置輸入。」* ..爲什麼?如果我輸入十行文字並在第三行發現錯誤,如果軟件不允許我編輯該行,我會非常煩惱。 –

回答

4

查看Protected Text Component,它允許您保護文檔的多個區域免受更改。

或者,如果你並不需要能夠「選擇」比任何一個簡單的解決方案保護的文字是使用NavigationFilter:

import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.text.*; 

public class NavigationFilterPrefixWithBackspace extends NavigationFilter 
{ 
    private int prefixLength; 
    private Action deletePrevious; 

    public NavigationFilterPrefixWithBackspace(int prefixLength, JTextComponent component) 
    { 
     this.prefixLength = prefixLength; 
     deletePrevious = component.getActionMap().get("delete-previous"); 
     component.getActionMap().put("delete-previous", new BackspaceAction()); 
     component.setCaretPosition(prefixLength); 
    } 

    @Override 
    public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias) 
    { 
     fb.setDot(Math.max(dot, prefixLength), bias); 
    } 

    @Override 
    public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias) 
    { 
     fb.moveDot(Math.max(dot, prefixLength), bias); 
    } 

    class BackspaceAction extends AbstractAction 
    { 
     @Override 
     public void actionPerformed(ActionEvent e) 
     { 
      JTextComponent component = (JTextComponent)e.getSource(); 

      if (component.getCaretPosition() > prefixLength) 
      { 
       deletePrevious.actionPerformed(null); 
      } 
     } 
    } 

    private static void createAndShowUI() 
    { 
     JTextField textField = new JTextField("Prefix_", 20); 
     textField.setNavigationFilter(new NavigationFilterPrefixWithBackspace(7, textField)); 

     JFrame frame = new JFrame("Navigation Filter Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(textField); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       createAndShowUI(); 
      } 
     }); 
    } 
} 
+0

+1比你的優秀課程 – mKorbel

3

好吧,這是稍微哈克......

基本上,這樣做是安裝一個「受保護」 DocumentFilter,這將只允許輸入把從某一點在Document

它覆蓋JTextAreainsert-break密鑰綁定(輸入)並記錄標記。 「受保護」 DocumentFilter然後確保內容不會先於這一點

我被迫在球場上實現KeyListener將光標移動到輸入端,而DocumentFilter是能夠處理這種情況,確實存在一些與刪除和一般可用性有關的問題。這也保證了選擇未強調當增加新的內容......

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.ActionMap; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.text.AbstractDocument; 
import javax.swing.text.AttributeSet; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.DocumentFilter; 

public class Terminal { 

    public static void main(String[] args) { 
     new Terminal(); 
    } 

    public Terminal() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JTextArea terminal = new JTextArea(20, 40); 
       ProtectedDocumentFilter.install(terminal); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new JScrollPane(terminal)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static interface UserInput { 

     public int getUserInputStart(); 

     public void setUserInputStart(int lastPoint); 
    } 

    public static class DefaultUserInput implements UserInput { 

     private final JTextArea textArea; 
     private int userInputStart; 

     public DefaultUserInput(JTextArea ta) { 
      textArea = ta; 
      ActionMap am = ta.getActionMap(); 
      Action action = am.get("insert-break"); 
      am.put("insert-break", new ProxyAction(action)); 

      ta.addKeyListener(new KeyAdapter() { 

       @Override 
       public void keyPressed(KeyEvent e) { 
        if (textArea.getCaretPosition() != textArea.getDocument().getLength()) { 
         textArea.setCaretPosition(textArea.getDocument().getLength()); 
        } 
       } 

      }); 
     } 

     @Override 
     public void setUserInputStart(int userInputStart) { 
      this.userInputStart = userInputStart; 
     } 

     @Override 
     public int getUserInputStart() { 
      return userInputStart; 
     } 

     public class ProxyAction extends AbstractAction { 

      private final Action proxy; 

      public ProxyAction(Action proxy) { 
       this.proxy = proxy; 
      } 

      @Override 
      public void actionPerformed(ActionEvent e) { 

       proxy.actionPerformed(e); 

       int range = textArea.getCaretPosition() - userInputStart; 
       userInputStart += range; 

      } 

     } 

    } 

    public static class ProtectedDocumentFilter extends DocumentFilter { 

     protected static void install(JTextArea textArea) { 
      UserInput ui = new DefaultUserInput(textArea); 
      ((AbstractDocument) textArea.getDocument()).setDocumentFilter(new ProtectedDocumentFilter(ui)); 
     } 

     private UserInput userInput; 

     public ProtectedDocumentFilter(UserInput userInput) { 
      this.userInput = userInput; 
     } 

     public UserInput getUserInput() { 
      return userInput; 
     } 

     @Override 
     public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { 
      if (offset < getUserInput().getUserInputStart()) { 
       offset = fb.getDocument().getLength(); 
      } 

      System.out.println("Insert"); 

      super.insertString(fb, offset, string, attr); 
     } 

     @Override 
     public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { 
      if (offset >= getUserInput().getUserInputStart()) { 
       super.remove(fb, offset, length); 
      } 
     } 

     @Override 
     public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { 
      if (offset < getUserInput().getUserInputStart()) { 
       offset = fb.getDocument().getLength(); 
       length = 0; 
      } 
      super.replace(fb, offset, length, text, attrs); 
      if (text.contains("\n")) { 
       int lastPoint = offset + text.lastIndexOf("\n"); 
       if (lastPoint > getUserInput().getUserInputStart()) { 
        getUserInput().setUserInputStart(lastPoint + 1); 
       } 
      } 
     } 
    } 

} 

這只是一個例子,你會需要它玩,並調整它來滿足自己的需要。 ...