【问题标题】:Moving a focus to Next JTextfield when it crosses it Jtextfieldlimit将焦点移到下一个 JTextfield 时,它越过它 Jtextfield 限制
【发布时间】:2016-01-27 12:14:04
【问题描述】:

我正在设计许可证激活部分。它在 Java Swing 中有两个文本字段。

Java 代码:

jTextField1.setDocument(new JTextFieldLimit(8));   
jTextField2.setDocument(new JTextFieldLimit(8));

当 jTextField1 通过输入 8 个字母数字字符结束时。它必须自动将焦点移到下一个 JTextField2。是否有可用的默认方法或如何完成。

【问题讨论】:

标签: java swing jtextfield


【解决方案1】:

您的问题的基本答案是,KeyboardFocusManager#focusNextCompnent

较长的答案稍微复杂一些。

让我们从 Java 1.4 开始,不再需要或建议您使用 Document 来实现此功能,而是使用 DocumentFilter,请参阅 Implementing a Document Filter 和 @ 987654323@了解更多详情

我也更喜欢可重用和可配置的解决方案,为此,我更希望看到一个解决方案,它允许我改变决定何时转移焦点并配置转移实际发生方式所涉及的决策过程

现在,请记住,您可以使用自定义 FocusTraversalPolicy 来更改焦点在组件之间移动的方式,但这并不总是理想的解决方案。

让我们从一些基础开始...

    public interface AutoFocusTransferDelegate {
        public boolean shouldTransferFocus(Document doc);
    }

    public interface AutoFocusTransferObserver {
        public void focusTransferShouldOccur(Document doc);
    }

    public class AutoFocusTransferHandler implements DocumentListener {

        private AutoFocusTransferListener listener;
        private AutoFocusTransferDelegate delegate;

        public AutoFocusTransferHandler(AutoFocusTransferListener listener, AutoFocusTransferDelegate delegate) {
            this.listener = listener;
            this.delegate = delegate;
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            checkForTransfer(e.getDocument());
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            checkForTransfer(e.getDocument());
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            checkForTransfer(e.getDocument());
        }

        public void checkForTransfer(Document doc) {
            if (delegate != null && delegate.shouldTransferFocus(doc)) {
                if (listener != null) {
                    listener.focusTransferShouldOccur(doc);
                }
            }
        }

    }

这里我们有一个“委托”,用于配置和自定义何时应该进行转移的决策过程,一个“观察者”,它在转移应该发生时得到通知,允许它决定“应该如何进行传输以及一个DocumentListener 来监视Document,该Document 用于查询委托并通知观察者。

当然,您可以将它们全部封装在一个类中,但是现在,您有一个非常简单且高度可配置的解决方案,您无需从类扩展即可获得新结果(我的部分)。这是组合优于继承的基本示例。

你也许可以使用它……

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.KeyboardFocusManager;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;

public class Test {

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

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

                JFrame frame = new JFrame("Testing");
                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() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            int maxCharacters = 8;
            AutoFocusTransferListener listener = new AutoFocusTransferListener() {
                @Override
                public void focusTransferShouldOccur(Document doc) {
                    KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
                }
            };
            AutoFocusTransferDelegate delegate = new MaxLengthAutoFocusTransferDelegate(maxCharacters);
            DocumentFilter filter = new SizeFilter(maxCharacters);
            DocumentListener docListener = new AutoFocusTransferHandler(listener, delegate);

            add(createTextField(8, filter, docListener), gbc);
            add(createTextField(8, filter, docListener), gbc);
            add(new JButton("Ok"), gbc);
        }

        protected  JTextField createTextField(int maxCharacters, DocumentFilter filter, DocumentListener docListener) {
            JTextField field = new JTextField(maxCharacters);
            AbstractDocument doc = (AbstractDocument)field.getDocument();
            doc.setDocumentFilter(filter);
            doc.addDocumentListener(docListener);
            return field;
        }

    }

    public class MaxLengthAutoFocusTransferDelegate implements AutoFocusTransferDelegate {

        private int maxLength;

        public MaxLengthAutoFocusTransferDelegate(int maxLength) {
            this.maxLength = maxLength;
        }

        @Override
        public boolean shouldTransferFocus(Document doc) {
            return doc.getLength() >= maxLength;
        }

    }

    public class SizeFilter extends DocumentFilter {

        private int maxCharacters;

        public SizeFilter(int maxChars) {
            maxCharacters = maxChars;
        }

        public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
                throws BadLocationException {

            if ((fb.getDocument().getLength() + str.length()) <= maxCharacters) {
                super.insertString(fb, offs, str, a);
            }
        }

        public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
                throws BadLocationException {

            if ((fb.getDocument().getLength() + str.length() - length) <= maxCharacters) {
                super.replace(fb, offs, length, str, a);
            }
        }
    }

    public class AutoFocusTransferHandler implements DocumentListener {

        private AutoFocusTransferListener listener;
        private AutoFocusTransferDelegate delegate;

        public AutoFocusTransferHandler(AutoFocusTransferListener listener, AutoFocusTransferDelegate delegate) {
            this.listener = listener;
            this.delegate = delegate;
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            checkForTransfer(e.getDocument());
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            checkForTransfer(e.getDocument());
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            checkForTransfer(e.getDocument());
        }

        public void checkForTransfer(Document doc) {
            if (delegate != null && delegate.shouldTransferFocus(doc)) {
                if (listener != null) {
                    listener.focusTransferShouldOccur(doc);
                }
            }
        }

    }

    public interface AutoFocusTransferDelegate {

        public boolean shouldTransferFocus(Document doc);
    }

    public interface AutoFocusTransferListener {

        public void focusTransferShouldOccur(Document doc);
    }
}

【讨论】:

    【解决方案2】:

    看看Component.requestFocus()

    【讨论】:

    • 当文本字段达到其限制时我将如何通知。
    • 你可以使用一个监听器来检查textfield.getText().length() == 8,然后改变焦点。
    猜你喜欢
    • 2013-12-25
    • 2016-07-31
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 2021-11-08
    • 2015-10-30
    • 2010-10-07
    • 1970-01-01
    相关资源
    最近更新 更多