【问题标题】:Force JTextField to string value while DocumentFilter only allows digits强制 JTextField 为字符串值,而 DocumentFilter 只允许数字
【发布时间】:2014-04-02 09:40:49
【问题描述】:

我正在开发一个 Java 应用程序,但遇到了一个我自己似乎无法解决的问题。

我在JTextField 上设置了DocumentFilter,只允许输入数字,但是,默认值是文本。我有一个将JTextFields 重置为默认值的按钮,它可能由于DocumentFilter 而无法工作。

我该如何克服这个问题?

谢谢

【问题讨论】:

  • 文字是什么?它不包含数字吗?文字的目的是什么?
  • 这是一个字符文本。正如我所说,这是默认值。
  • @Yury Lankovskiy 可能是一个有趣的问题,你的要求让我感觉,但这里将基于你的 SSCCE / MCVE / MCTRE,简短,可运行,可在局部变量中使用硬编码值进行编译
  • @mKorbel 我不知道你在说什么。
  • 我问的原因是你可以使用来自 SwingLabs SwingX 库的PromptSupport 之类的东西,用于example

标签: java swing jtextfield digit documentfilter


【解决方案1】:

做一件事:

将默认文档存储在某个位置

final JTextField textField = new JTextField();
final Document defaultDocument=textField.getDocument();

单击按钮时首先将文档设置回默认值以禁用文本字段上的验证,然后设置默认文本

 btn.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        textField.setDocument(defaultDocument);
        textField.setText("hi");
    }
});

将您的文档过滤器重新添加回文本字段中的焦点以验证用户输入。

请查看How to implement in Java ( JTextField class ) to allow entering only digits?


-- 编辑--

您可以通过在text field 上添加focus listener 来实现。

如果文本字段中的值为空,则将默认值设置回作为提示。单击按钮时无需执行此操作。

代码如下:

    final JTextField textField = new JTextField("First Name");

    final Document defaultDocument = textField.getDocument();

    final PlainDocument doc = new PlainDocument();
    doc.setDocumentFilter(new DocumentFilter() {
        @Override
        public void insertString(FilterBypass fb, int off, String str, AttributeSet attr)
                throws BadLocationException {
            fb.insertString(off, str.replaceAll("\\D++", ""), attr); // remove
                                                                     // non-digits
        }

        @Override
        public void replace(FilterBypass fb, int off, int len, String str,
                AttributeSet attr) throws BadLocationException {
            fb.replace(off, len, str.replaceAll("\\D++", ""), attr); // remove
                                                                     // non-digits
        }
    });

    textField.addFocusListener(new FocusListener() {

        @Override
        public void focusLost(FocusEvent e) {
            System.out.println("focus lost");
            if(textField.getText() == null || textField.getText().trim().length()==0){
                textField.setDocument(defaultDocument);
                textField.setText("First Name");
            }
        }

        @Override
        public void focusGained(FocusEvent e) {
            System.out.println("focus gained");
            textField.setDocument(doc);
        }
    });

【讨论】:

  • 是的 OP 可以在运行时完成。 OP 只需要两个文档过滤器,一个用于默认,第二个用于数字。
  • 谢谢,但我改用 PromptSupport,它更容易。
  • 继续PromptSupport
【解决方案2】:

用户只能输入数字数据,但又需要显示非数字值的字段是矛盾的。

文本通过Document 提供给字段,无论是由用户还是以编程方式生成该内容,都没有区别。

如果您想在字段中显示“提示”,您可以查看PromptSupport in SwingLabs SwingX Library

举例

当字段获得焦点时,“提示”将被隐藏,但您可以控制它,使其显示直到用户键入内容或获得焦点时突出显示。

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
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 org.jdesktop.swingx.prompt.BuddySupport;
import org.jdesktop.swingx.prompt.PromptSupport;

public class PromptSupportTest {

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

    public PromptSupportTest() {
        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() {
            JTextField firstName = new JTextField(10);
            PromptSupport.setPrompt("First Name", firstName);
            PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, firstName);

            JTextField lastName = new JTextField(10);
            PromptSupport.setPrompt("Last Name", lastName);
            PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, lastName);

            JTextField picture = new JTextField(10);
            PromptSupport.setPrompt("Picture", picture);
            PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, picture);

            JButton browse = new JButton("...");
            browse.setMargin(new Insets(0, 0, 0, 0));
            browse.setContentAreaFilled(false);
            browse.setFocusPainted(false);
            browse.setFocusable(false);
            browse.setOpaque(false);
            // Add action listener to brose button to show JFileChooser...

            BuddySupport.addRight(browse, picture);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;

            add(firstName, gbc);
            add(lastName, gbc);
            add(picture, gbc);

            gbc.anchor = GridBagConstraints.CENTER;
            add(new JButton("Ok"), gbc);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

我还添加了BuddySupport 的示例,它是同一 API 的一部分,它允许您将另一个组件与文本组件“结成伙伴”。这里我做了经典的“文件浏览器”组合,但我一直在做这样的“搜索”样式字段……

【讨论】:

    【解决方案3】:

    你可以使用类似 PromptSupport 的东西

    或者可能是Text Prompt 类。它类似于 PromptSupport,但可以在常规 JTextField 上使用,因此您不需要整个 SwingX 项目。

    【讨论】:

      猜你喜欢
      • 2012-08-04
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      • 2012-03-17
      • 2010-12-09
      相关资源
      最近更新 更多