Java 如何创建忽略用户输入但允许组件修改文本的JTextField?

Java 如何创建忽略用户输入但允许组件修改文本的JTextField?,java,swing,jtextfield,Java,Swing,Jtextfield,以下是我想要的概念证明:我想要一个带有文本字段和按钮的框架。用户在文本字段中键入的任何内容都将被忽略,但如果单击该按钮,它将在文本字段中设置文本。你会怎么做 我已经提前做了一些研究,并提出了一个解决方案,我将作为答案发布。但我担心的是,有一种更简单的方法可以做到这一点。我问这个问题是想知道是否有更好的方法 以下是我尝试构建此概念验证的原因的截图: 我正试着建造这样的东西。当用户输入文本时,我想忽略他们所说的内容,捕捉它,并给出我自己的解释。例如,如果用户按下control+Y,我希望它这样说:

以下是我想要的概念证明:我想要一个带有文本字段和按钮的框架。用户在文本字段中键入的任何内容都将被忽略,但如果单击该按钮,它将在文本字段中设置文本。你会怎么做

我已经提前做了一些研究,并提出了一个解决方案,我将作为答案发布。但我担心的是,有一种更简单的方法可以做到这一点。我问这个问题是想知道是否有更好的方法

以下是我尝试构建此概念验证的原因的截图:

我正试着建造这样的东西。当用户输入文本时,我想忽略他们所说的内容,捕捉它,并给出我自己的解释。例如,如果用户按下control+Y,我希望它这样说:


我不想简单地使JTextField不可编辑,因为这会使框变灰并隐藏光标。我想让人们知道他们应该单击文本字段并键入

这段代码正是我想要的。但我希望有一个更简单的方法:

package com.sandbox;

import javax.swing.*;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Sandbox {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        final JTextField text = new JTextField();
        ((AbstractDocument) text.getDocument()).setDocumentFilter(new DocumentFilter() {
            @Override
            public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
//                super.remove(fb, offset, length);
            }

            @Override
            public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
//                super.insertString(fb, offset, string, attr);
            }

            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
//                super.replace(fb, offset, length, text, attrs);
            }
        });

        JPanel panel = new JPanel();
        BoxLayout layout = new BoxLayout(panel, BoxLayout.Y_AXIS);
        panel.setLayout(layout);

        panel.add(text);
        JButton jButton = new JButton("Click to change text");
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DocumentFilter old = ((AbstractDocument) text.getDocument()).getDocumentFilter();
                ((AbstractDocument) text.getDocument()).setDocumentFilter(new DocumentFilter());
                text.setText("You clicked!");
                ((AbstractDocument) text.getDocument()).setDocumentFilter(old);
            }
        });
        panel.add(jButton);

        frame.setContentPane(panel);

        frame.pack();
        frame.setVisible(true);
    }


}

这段代码正是我想要的。但我希望有一个更简单的方法:

package com.sandbox;

import javax.swing.*;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Sandbox {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        final JTextField text = new JTextField();
        ((AbstractDocument) text.getDocument()).setDocumentFilter(new DocumentFilter() {
            @Override
            public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
//                super.remove(fb, offset, length);
            }

            @Override
            public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
//                super.insertString(fb, offset, string, attr);
            }

            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
//                super.replace(fb, offset, length, text, attrs);
            }
        });

        JPanel panel = new JPanel();
        BoxLayout layout = new BoxLayout(panel, BoxLayout.Y_AXIS);
        panel.setLayout(layout);

        panel.add(text);
        JButton jButton = new JButton("Click to change text");
        jButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DocumentFilter old = ((AbstractDocument) text.getDocument()).getDocumentFilter();
                ((AbstractDocument) text.getDocument()).setDocumentFilter(new DocumentFilter());
                text.setText("You clicked!");
                ((AbstractDocument) text.getDocument()).setDocumentFilter(old);
            }
        });
        panel.add(jButton);

        frame.setContentPane(panel);

        frame.pack();
        frame.setVisible(true);
    }


}

使文本字段不可编辑。用户无法输入数据,但程序仍可以:

textField.setEditable(false);

使文本字段不可编辑。用户无法输入数据,但程序仍可以:

textField.setEditable(false);

如果要保持光标,可以按所述截取击键

以上链接的代码:

myTextField.addKeyListener(new KeyAdapter() {
    @Override
    public void keyTyped(KeyEvent e) {
        char c = e.getKeyChar();
        if (!Character.isDigit(c)) {
            e.consume(); // Stop the event from propagating.
        }
    }
});
或者,您可以禁用输入,然后轻松恢复背景色,但会丢失光标:

textField.setEditable(false);
textField.setBackground(Color.WHITE);

如果要保持光标,可以按所述截取击键

以上链接的代码:

myTextField.addKeyListener(new KeyAdapter() {
    @Override
    public void keyTyped(KeyEvent e) {
        char c = e.getKeyChar();
        if (!Character.isDigit(c)) {
            e.consume(); // Stop the event from propagating.
        }
    }
});
或者,您可以禁用输入,然后轻松恢复背景色,但会丢失光标:

textField.setEditable(false);
textField.setBackground(Color.WHITE);

这是的编辑版本。它还可以防止类似于Ctrl+V的操作,因为该事件也会在
按键
按键释放
方法中使用

myTextField.addKeyListener(new KeyListener() {
    @Override
    public void keyTyped(KeyEvent ke) {
        ke.consume();
        // do what you want:
        myTextField.setText(...);
    }
    @Override
    public void keyPressed(KeyEvent ke) {
        ke.consume();
    }
    @Override
    public void keyReleased(KeyEvent ke) {
        ke.consume();
    }
});

这是的编辑版本。它还可以防止类似于Ctrl+V的操作,因为该事件也会在
按键
按键释放
方法中使用

myTextField.addKeyListener(new KeyListener() {
    @Override
    public void keyTyped(KeyEvent ke) {
        ke.consume();
        // do what you want:
        myTextField.setText(...);
    }
    @Override
    public void keyPressed(KeyEvent ke) {
        ke.consume();
    }
    @Override
    public void keyReleased(KeyEvent ke) {
        ke.consume();
    }
});

我不喜欢文本字段变灰并隐藏光标的方式。我将更新我的问题,使其更加具体。我不喜欢这样会使文本字段变灰并隐藏光标。我将更新我的问题,使其更加具体。文本字段不会接收“控制”击键,只接收生成键类型事件的击键。也许你可以有几个复选框(Control、Alt、Shift)和一个包含a-z、0-9的组合框。当用户进行选择时,您进行翻译并在JLabel中显示结果。@camickr是的,但我已经了解了细节。文本字段不会接收“控制”击键,只接收生成键类型事件的击键。也许你可以有几个复选框(Control、Alt、Shift)和一个包含a-z、0-9的组合框。当用户做出选择时,您进行翻译并在JLabel中显示结果。@camickr是的,但我已经了解了这个细节。Re:第一个示例,我的理解是,这不会捕获Control+V(粘贴),最终会显示剪贴板。第二种是可以的,但是如果没有光标,我认为它会让用户感到困惑。由于事件通知的性质,这可能不适用于所有的p、at表单,并且不推荐用于拦截输入。DocumentFilter是正确的方法,但根据tieTYL的回答,似乎正在寻找替代方法。Re:第一个例子,我的理解是,它不会捕获Control+V(粘贴),最终会显示剪贴板。第二种是可以的,但是如果没有光标,我认为它会让用户感到困惑。由于事件通知的性质,这可能不适用于所有的p、at表单,并且不推荐用于拦截输入。DocumentFilter是正确的方法,但根据tieTYL的回答,似乎正在寻找替代方法。