java - 为什么 DocumentFilter 没有给出预期的结果?

标签 java swing jtextfield documentfilter

我认为这一定是代码中的一个简单错误或我的误解,但我无法获得 DocumentFilter 来检测 insertString 事件。下面是一个简单的大写字母过滤器,但这并不重要,因为 insertString(..) 方法似乎从未被调用过!

为什么 DocumentFilterinsertString(..) 方法没有被调用?

过滤器应用于顶部的 JTextField。每次调用 insertString(..) 时,它都应该将信息附加到 CENTER 中的 JTextArea。目前,文本字段中没有导致文本附加到文本区域的操作。

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.*;

public class FilterUpperCaseLetters {

    private JComponent ui = null;
    private final JTextField textField = new JTextField(25);
    private final JTextArea textArea = new JTextArea(5, 20);

    FilterUpperCaseLetters() {
        initUI();
    }

    public void initUI() {
        // The document filter that seems to do nothing.
        DocumentFilter capsFilter = new DocumentFilter() {
            @Override
            public void insertString(
                    DocumentFilter.FilterBypass fb,
                    int offset,
                    String string,
                    AttributeSet attr) throws BadLocationException {
                textArea.append("insertString! " + string + "\n");
                if (!string.toUpperCase().equals(string)) {
                    textArea.append("Insert!\n");
                    super.insertString(fb, offset, string, attr);
                } else {
                    textArea.append("DON'T insert!\n");
                }
            }
        };
        AbstractDocument abstractDocument
                = (AbstractDocument) textField.getDocument();
        abstractDocument.setDocumentFilter(capsFilter);

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        ui.add(textField, BorderLayout.PAGE_START);
        ui.add(new JScrollPane(textArea), BorderLayout.CENTER);
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                FilterUpperCaseLetters o = new FilterUpperCaseLetters();

                JFrame f = new JFrame(o.getClass().getSimpleName());
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.setContentPane(o.getUI());
                f.pack();
                f.setMinimumSize(f.getSize());

                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

最佳答案

文本组件使用 replaceSelection(...)方法将依次调用 replace(...) AbstractDocument 的方法这将调用 replace(...) DocumentFilter 的方法.

insertString(...) DocumentFilter 的方法仅在您使用 Document.insertString(...) 时调用直接更新 Document 的方法.

因此实际上您需要重写这两个方法以确保完成大写转换。

一个简单的例子展示了如何轻松地实现这两种方法:

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

public class UpperCaseFilter extends DocumentFilter
{
    public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
        throws BadLocationException
    {
        replace(fb, offs, 0, str, a);
    }

    public void replace(FilterBypass fb, final int offs, final int length, final String text, final AttributeSet a)
        throws BadLocationException
    {
        if (text != null)
        {
            super.replace(fb, offs, length, text.toUpperCase(), a);
        }
    }

    private static void createAndShowGUI()
    {
        JTextField textField = new JTextField(10);
        AbstractDocument doc = (AbstractDocument) textField.getDocument();
        doc.setDocumentFilter( new UpperCaseFilter() );

        JFrame frame = new JFrame("Upper Case Filter");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout( new java.awt.GridBagLayout() );
        frame.add( textField );
        frame.setSize(220, 200);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args) throws Exception
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}

关于java - 为什么 DocumentFilter 没有给出预期的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31487465/

相关文章:

java传递JFrame可以接受吗?

java - 如何从矩阵访问 JButton

java - 如果获得焦点如何清空 JTextField

Java,如何重置 JTextField

java - 如何在速度工具中获取 HttpServletRequest?

java - 如何从列表中获取重复值的数量(计数)

java - JUnit 在 Linux 上安装失败

java - 如何通过 Sort 和 Pageable 使用 Spring data JPA 开箱即用地查询数据?

java - 从 MySQL 数据库中检索数据并在 JTable 中显示

java - 循环 jtextfields,以便清除是否输入了除整数之外的任何内容