Java:游标中的错误自动从一个TextField移动到另一个TextField

时间:2017-03-10 01:57:53

标签: java swing awt

当我输入TextField 7字符时,光标会自动移动到下一个TextField。但在我的代码中,我的光标没有转到nextField。 (我知道我不能使用addKeyListener,因此尝试将DocumentListener用于此代码)

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

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

2 个答案:

答案 0 :(得分: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%确定

答案 1 :(得分:1)

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

  1. 有两个类,一个用于限制字符,另一个用于标记,或
  2. 有一个课程来限制字符并进行标记
  3. 你有第一种方法的解决方案。

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

    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中提出的解决方案,该解决方案提供了嵌套DocumentFilters的方法。