2011-09-14 71 views
4

考慮一個JFormattedTextField(或者任何真正的JTextComponent),其中前綴和後綴顯示在字段的實際「文本」的周圍。JTextField/JTextComponent中的選擇有限嗎?

例如,雙3.5將是字符串(通過格式)「3.50」,其前綴爲「$」,後綴爲「」,顯示文本爲「$ 3.50」。

顯然,這很容易做到。但是,用戶仍然可以在前綴/後綴中選擇文本,因此他們可以設想刪除部分或全部前綴/後綴。我寧願限制用戶,以至於根本不能選擇前綴/後綴(儘管仍然是文本字段的一部分,所以沒有JLabel)。我幾乎可以用CaretListener(或通過覆蓋setCaretPosition/moveCaretPosition)來完成此操作,這可以防止C-a選擇整個字段,並且可以防止使用箭頭鍵移動到前綴/後綴中。但是,鼠標拖動和換檔箭頭鍵仍然允許選擇移動到這些限制區域。

任何想法?

回答

6

您可以爲此使用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); 
    } 

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

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

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

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

    public static void main(String args[]) throws Exception { 

     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); 
    } 
} 

我相信這是一個JFormattedTextField的是如何工作的。所以我不確定你是否可以使用格式化文本字段來替代默認行爲。

+0

我想感謝您的回答,NavigationFilters顯然是正確的解決方案。關於格式化的文本字段,AbstractFormatter具有可覆蓋的getNavigationFilter(),它將這些字段中的一個應用於該字段。這正是我需要的。 –