2017-03-10 69 views
0

当我输入TextField 7字符时,光标自动移动到下一个TextField。但在我的代码中,我的光标没有进入nextField。 (我知道我不能使用addKeyListener,所以试图用的DocumentListener此代码)Java:光标中的错误自动从一个TextField移动到其他

lbltext1 = new JLabel("Text1"); 
panel.add(lbltext1, "cell 0 1,alignx trailing"); 
final int maxSize =7 ; 
for (int i = 0; i < 1; i++) { 
    final JTextField txtText1 = new JTextField(); 
    NavigationFilter filter = new NavigationFilter() { 
     @Override 
     public void setDot(FilterBypass fb, int dot, Bias bias) { 
      if (dot >= maxSize) { 
       fb.setDot(0, bias); 
       txtText1.transferFocus(); 
       return; 
      } 
      fb.setDot(dot, bias); 
     } 

     @Override 
     public void moveDot(FilterBypass fb, int dot, Bias bias) { 
      if (dot >= maxSize) { 
       fb.setDot(0, bias); 
       txtText1.transferFocus(); 
       return; 
      } 
      fb.moveDot(dot, bias); 
     } 
    };  
    txtText1.addFocusListener(new FocusAdapter() { 
      @Override 
      public void focusLost(FocusEvent arg0) { 

       if (txtText1.getText().equals("")) { 
        txtDate.setText(""); 
       } else { 
        SwingWorker<?, ?> job = new UIQuery(); 
       job.execute(); 
       } 
     } 
    });   
    txtText1.setNavigationFilter(filter); 
    ((AbstractDocument) txtText1.getDocument()).setDocumentFilter(new DocumentSizeFilter(maxSize)); 
    panel.add(txtText1, "cell 1 1,growx"); 
    txtText1.setColumns(10); 
} 
JLabel lblText2 = new JLabel("Production Date"); 
panel.add(lblText2, "cell 0 2,alignx trailing"); 
txtText2 = new JTextField(); 
panel.add(txtText2, "flowx,cell 1 2,growx"); 
txtText2.setColumns(10); 
txtText2.addFocusListener(new TextBoxGainedFocusEventSinglePreview()); 
txtText2.getDocument().addDocumentListener(new TextBoxDataChangedEventSinglePreview()); 

请告知我应该如何修改它。 感谢

+0

当字段有7个字符或用户输入'7'时,您想要传送焦点吗? – MadProgrammer

+0

@MadProgrammer,用户在textField上输入7个字符后.. – JavaIssues

回答

2

所以,这是观念的一个简单证明,这将焦点从当前组件移动到下一个时相比,现场的Document长度> 6

import java.awt.KeyboardFocusManager; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 
import javax.swing.event.DocumentEvent; 
import javax.swing.event.DocumentListener; 

public class Test { 

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

    public Test() { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      JTextField field1 = new JTextField(7); 
      JTextField field2 = new JTextField(7); 

      add(field1); 
      add(field2); 

      field1.getDocument().addDocumentListener(new DocumentListener() { 
       @Override 
       public void insertUpdate(DocumentEvent e) { 
        if (e.getDocument().getLength() > 6) { 
         //field1.transferFocus(); 
         KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(); 
        } 
       } 

       @Override 
       public void removeUpdate(DocumentEvent e) { 
       } 

       @Override 
       public void changedUpdate(DocumentEvent e) { 
        if (e.getDocument().getLength() > 6) { 
         //field1.transferFocus(); 
         KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(); 
        } 
       } 
      }); 
     } 

    } 
} 

当事情不工作,通过删除启动不需要测试它的所有东西(即DocumentFilterNavigationFilter),只要你知道它正在工作,就可以将它作为一个孤立的状态工作,一次重新引入其他元素,并确保没有任何中断。

这有可能是DocumentSizeFilter可能与它的干扰,但我没有足够的上下文是100%肯定

+0

感谢您的宝贵意见。 =) 感谢您的帮助。 – JavaIssues

+0

希望它可以帮助;) – MadProgrammer

1

不知道还有什么更好的设计是:

  1. 有两台类,一个限制字符和其他做黏合,或
  2. 有一个类来限制字符和做互联

你有一个搜索解决方案n为第一种方法。

对于第二种方法,您可以检查出:

import java.awt.Component; 
import java.awt.KeyboardFocusManager; 
import java.awt.Toolkit; 
import javax.swing.JTextField; 
import javax.swing.text.AttributeSet; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.AbstractDocument; 
import javax.swing.text.Document; 
import javax.swing.text.DocumentFilter; 
import javax.swing.text.DocumentFilter.FilterBypass; 
import javax.swing.text.JTextComponent; 

/** 
* A DocumentFilter that allows you to control the maximum number of 
* characters that can be added to the Document. When the Document is 
* full you can optionally tab to the next component to speed data entry. 
* 
* This class can also be used as a generic size filter for JTextFields. In 
* this case when a size of 0 is speicifed for the size of the Document the 
* getColumns() method of JTextField will be used to determine the size 
* restriction. 
*/ 
public class TabDocumentFilter extends DocumentFilter 
{ 
    private int size; 
    private boolean autoTab = true; 

    /** 
    * Generic constructor for use with JTextFields only. The size of the 
    * Document will be determined by the value of the getColumns() method. 
    */ 
    public TabDocumentFilter() 
    { 
     this(0); 
    } 

    /** 
    * Constructor to set the size for this filter 
    * 
    * @param size maximum number of characters to be added to the Document 
    */ 
    public TabDocumentFilter(int size) 
    { 
     setSize(size); 
    } 

    /** 
    * Get the auto tab property 
    * 
    * @return the auto tab property 
    */ 
    public boolean getAutoTab() 
    { 
     return autoTab; 
    } 

    /** 
    * Set the auto tab property 
    * 
    * @param autoTab the default is true 
    */ 
    public void setAutoTab(boolean autoTab) 
    { 
     this.autoTab = autoTab; 
    } 

    /** 
    * Get the maximum size for any Document using this filter 
    * 
    * @return 
    */ 
    public int getSize() 
    { 
     return size; 
    } 

    /** 
    * Set maximum size for a Document using this filter. Dynamically changing 
    * the size will not affect existing Documents. Characters will not be 
    * removed from any Document. The filter will only be invoked on new 
    * additions to the Document. 
    * 
    * @param size the maximum number of character allowed in the Document 
    */ 
    public void setSize(int size) 
    { 
     this.size = size; 
    } 

    /** 
    * Install this filter on the AbstractDocument 
    * 
    * @param components the text components that will use this filter 
    */ 
    public void installFilter(JTextComponent... components) 
    { 
     for (JTextComponent component : components) 
     { 
      Document doc = component.getDocument(); 

      if (doc instanceof AbstractDocument) 
      { 
       ((AbstractDocument)doc).setDocumentFilter(this); 
      } 
     } 
    } 

    /** 
    * Make sure the insertion of text will not cause the Document to exceed 
    * its size limit. Also, potentially tab to next component when full. 
    */ 
    @Override 
    public void insertString(FilterBypass fb, int offs, String str, AttributeSet a) 
     throws BadLocationException 
    { 
     int possibleSize = fb.getDocument().getLength() + str.length(); 
     int allowedSize = getAllowedSize(fb); 

     if (possibleSize <= allowedSize) 
     { 
      super.insertString(fb, offs, str, a); 
      handleAutoTab(possibleSize, allowedSize, fb); 
     } 
     else 
     { 
      Toolkit.getDefaultToolkit().beep(); 
     } 
    } 

    /** 
    * Make sure the replacement of text will not cause the Document to exceed 
    * its size limit. Also, potentially tab to next component when full. 
    */ 
    @Override 
    public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a) 
     throws BadLocationException 
    { 
     int possibleSize = fb.getDocument().getLength() + str.length() - length; 
     int allowedSize = getAllowedSize(fb); 

     if (possibleSize <= allowedSize) 
     { 
      super.replace(fb, offs, length, str, a); 
      handleAutoTab(possibleSize, allowedSize, fb); 
     } 
     else 
     { 
      Toolkit.getDefaultToolkit().beep(); 
     } 
    } 

    /** 
    * When a size isn't specified then we assume the desired size can be 
    * obtained from the associated text field. Otherwise, use the class 
    * size property. 
    */ 
    private int getAllowedSize(FilterBypass fb) 
    { 
     return (size == 0) ? getColumns(fb) : size; 
    } 

    /* 
    * Use the value returnd by invoking the getColumns() method of JTextField 
    */ 
    private int getColumns(FilterBypass fb) 
    { 
     // Find the text field that currently has focus 
     // and make sure it is using the Document that will be updated 

     Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 

     if (c != null && c instanceof JTextField) 
     { 
      JTextField textField = (JTextField)c; 
      Document doc = textField.getDocument(); 

      if (doc.equals(fb.getDocument())) 
      { 
       return textField.getColumns(); 
      } 
     } 

     return 0; 
    } 

    /* 
    * When the Document is full tab to the next component. 
    */ 
    protected void handleAutoTab(int possibleSize, int allowedSize, FilterBypass fb) 
    { 
     if (autoTab == false 
     || possibleSize != allowedSize) 
      return; 

     // Find the text field that currently has focus 
     // and make sure it is using the Document that has been updated 

     Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 

     if (c != null && c instanceof JTextComponent) 
     { 
      JTextComponent component = (JTextComponent)c; 
      Document doc = component.getDocument(); 

      if (doc.equals(fb.getDocument())) 
      { 
       c.transferFocus(); 
      } 
     } 
    } 
} 

要使用它,你可以这样做:

TabDocumentFilter tf = new TabDocumentFilter(); 
tf.installFilter(textField1, textField2); 

每个文本字段的字符将被限制基础上的数量为文本字段和自动标签指定的列将会发生。

上述解决方案基于Text Field Auto Tab中提出的解决方案,该解决方案提供了嵌套DocumentFilter的方法。