Daniel Kaplan
Daniel Kaplan

Reputation: 67340

How do I create a JTextField that ignores user input but lets components modify text?

Here's what I'd like as a proof of concept: I want a Frame with a text field and a button on it. Anything the user types into the text field is ignored, but if you click the button, it sets the text on the text field. How would you do this?

I've done some research ahead of time and come up with a solution that I'll post as an answer. But my concern is that there's a much easier way to do this. I'm asking the question to find out if there's a better way.

Here's a screenshot of the reason I'm trying to build this proof of concept:

capture key inputs

I'm trying to build something just like this. When user enters text, I want to ignore what they are saying, capture it, and put my own interpretation. For example, if the user pressed control+Y, I want it to say this:

key input captured

I don't want to simply make the JTextField un-editable, because that grays out the box and hides the cursor. I want people to know they should click on the text field and type.

Upvotes: 1

Views: 8211

Answers (4)

Aloso
Aloso

Reputation: 5387

This is an edited version of hendalst' code. It also prevents things like Ctrl+V because the event is also consumed in the keyPressed and keyReleased methods.

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

Upvotes: 2

hendalst
hendalst

Reputation: 3085

If you want to maintain the cursor, you can intercept the keystrokes as described here.

Code from above link:

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.
        }
    }
});

Alternatively, you can disable entry and then restore the background color easily enough, but lose the cursor:

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

Upvotes: 3

camickr
camickr

Reputation: 324108

Make the text field non-editable. The user can't enter data, but the program still can:

textField.setEditable(false);

Upvotes: 2

Daniel Kaplan
Daniel Kaplan

Reputation: 67340

This snippet of code does exactly what I want. But I'm hoping there's an easier way:

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


}

Upvotes: 0

Related Questions