Reputation: 67340
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:
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:
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
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
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
Reputation: 324108
Make the text field non-editable. The user can't enter data, but the program still can:
textField.setEditable(false);
Upvotes: 2
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