Hi I am trying to use setDocument method to limit the number of characters a user can input in the text field. But somehow it does not limit the no of input characters. Here's the code
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
public class JTextFieldCharLimit extends PlainDocument {
private int limit;
public JTextFieldCharLimit(int limit)
{
super();
this.limit = limit;
}
public void inserString(int offset, String str, AttributeSet set) throws BadLocationException
{
if(str == null)
{
return;
} else if((getLength() + str.length()) <= limit)
{
str = str.toUpperCase();
super.insertString(offset, str, set);
}
}
}
I am using this class in another class where I have declared my text field as follows:
void playerInfoScreen(JFrame mainFrame, JPanel menuPanel)
{
final ScreenConstructor playerName = new ScreenConstructor();
final JFrame frame = mainFrame;
final JPanel returnPanel = menuPanel;
final JPanel panel = playerName.createPanel("menu panel");
final JButton returnButton = playerName.createButton("MAIN MENU");
final JTextField textEntry = playerName.createTextField(10);
// text field length needs to be set to prevent long texts
final JLabel label = playerName.createLabel("Enter Player Name:");
playerName.addButtonToPanel(panel, returnButton);
playerName.addLabelToPanel(panel, label);
playerName.addJTextFieldToPanel(panel, textEntry);
textEntry.setDocument(new JTextFieldCharLimit(5));
playerName.displayScreen(frame, panel);
// check for esc button to let user return back to main menu
textEntry.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String player = textEntry.getText(); // save entered player name
storedPlayerName = player; // store player in order to use it in highscores and display on game screen
GameScreen game = new GameScreen(frame, panel); // go to game screen
}
});
returnButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
frame.setContentPane(returnPanel); // go back to previous panel
}
});
}
Use a DocumentFilter. See Implementing a Document Filter and DocumentFilter Examples for more details.
public class SizeFilter extends DocumentFilter {
private int maxCharacters;
public SizeFilter(int maxChars) {
maxCharacters = maxChars;
}
public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
throws BadLocationException {
if ((fb.getDocument().getLength() + str.length()) <= maxCharacters)
super.insertString(fb, offs, str, a);
else
Toolkit.getDefaultToolkit().beep();
}
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
throws BadLocationException {
if ((fb.getDocument().getLength() + str.length()
- length) <= maxCharacters)
super.replace(fb, offs, length, str, a);
else
Toolkit.getDefaultToolkit().beep();
}
}
Credit to MDP
((AbstractDocument)textEntry.getDocument()).setDocumentFilter(new SizeFilter(5));
Related
How to limit the number of characters entered in a JTextField?
Suppose I want to enter say 5 characters max. After that no characters can be entered into it.
http://www.rgagnon.com/javadetails/java-0198.html
import javax.swing.text.PlainDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
public class JTextFieldLimit extends PlainDocument {
private int limit;
JTextFieldLimit(int limit) {
super();
this.limit = limit;
}
public void insertString( int offset, String str, AttributeSet attr ) throws BadLocationException {
if (str == null) return;
if ((getLength() + str.length()) <= limit) {
super.insertString(offset, str, attr);
}
}
}
Then
import java.awt.*;
import javax.swing.*;
public class DemoJTextFieldWithLimit extends JApplet{
JTextField textfield1;
JLabel label1;
public void init() {
getContentPane().setLayout(new FlowLayout());
//
label1 = new JLabel("max 10 chars");
textfield1 = new JTextField(15);
getContentPane().add(label1);
getContentPane().add(textfield1);
textfield1.setDocument
(new JTextFieldLimit(10));
}
}
(first result from google)
If you wanna have everything into one only piece of code, then you can mix tim's answer with the example's approach found on the API for JTextField, and you'll get something like this:
public class JTextFieldLimit extends JTextField {
private int limit;
public JTextFieldLimit(int limit) {
super();
this.limit = limit;
}
#Override
protected Document createDefaultModel() {
return new LimitDocument();
}
private class LimitDocument extends PlainDocument {
#Override
public void insertString( int offset, String str, AttributeSet attr ) throws BadLocationException {
if (str == null) return;
if ((getLength() + str.length()) <= limit) {
super.insertString(offset, str, attr);
}
}
}
}
Then there is no need to add a Document to the JTextFieldLimit due to JTextFieldLimit already have the functionality inside.
Read the section from the Swing tutorial on Implementing a DocumentFilter for a more current solution.
This solution will work an any Document, not just a PlainDocument.
This is a more current solution than the one accepted.
Great question, and it's odd that the Swing toolkit doesn't include this functionality natively for JTextFields. But, here's a great answer from my Udemy.com course "Learn Java Like a Kid":
txtGuess = new JTextField();
txtGuess.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
if (txtGuess.getText().length() >= 3 ) // limit textfield to 3 characters
e.consume();
}
});
This limits the number of characters in a guessing game text field to 3 characters, by overriding the keyTyped event and checking to see if the textfield already has 3 characters - if so, you're "consuming" the key event (e) so that it doesn't get processed like normal.
Just Try This :
textfield.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyTyped(java.awt.event.KeyEvent evt) {
if(textfield.getText().length()>=5&&!(evt.getKeyChar()==KeyEvent.VK_DELETE||evt.getKeyChar()==KeyEvent.VK_BACK_SPACE)) {
getToolkit().beep();
evt.consume();
}
}
});
I have solved this problem by using the following code segment:
private void jTextField1KeyTyped(java.awt.event.KeyEvent evt) {
boolean max = jTextField1.getText().length() > 4;
if ( max ){
evt.consume();
}
}
import java.awt.KeyboardFocusManager;
import javax.swing.InputVerifier;
import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;
/**
*
* #author Igor
*/
public class CustomLengthTextField extends JTextField {
protected boolean upper = false;
protected int maxlength = 0;
public CustomLengthTextField() {
this(-1);
}
public CustomLengthTextField(int length, boolean upper) {
this(length, upper, null);
}
public CustomLengthTextField(int length, InputVerifier inpVer) {
this(length, false, inpVer);
}
/**
*
* #param length - maksimalan length
* #param upper - turn it to upercase
* #param inpVer - InputVerifier
*/
public CustomLengthTextField(int length, boolean upper, InputVerifier inpVer) {
super();
this.maxlength = length;
this.upper = upper;
if (length > 0) {
AbstractDocument doc = (AbstractDocument) getDocument();
doc.setDocumentFilter(new DocumentSizeFilter());
}
setInputVerifier(inpVer);
}
public CustomLengthTextField(int length) {
this(length, false);
}
public void setMaxLength(int length) {
this.maxlength = length;
}
class DocumentSizeFilter extends DocumentFilter {
public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
throws BadLocationException {
//This rejects the entire insertion if it would make
//the contents too long. Another option would be
//to truncate the inserted string so the contents
//would be exactly maxCharacters in length.
if ((fb.getDocument().getLength() + str.length()) <= maxlength) {
super.insertString(fb, offs, str, a);
}
}
public void replace(FilterBypass fb, int offs,
int length,
String str, AttributeSet a)
throws BadLocationException {
if (upper) {
str = str.toUpperCase();
}
//This rejects the entire replacement if it would make
//the contents too long. Another option would be
//to truncate the replacement string so the contents
//would be exactly maxCharacters in length.
int charLength = fb.getDocument().getLength() + str.length() - length;
if (charLength <= maxlength) {
super.replace(fb, offs, length, str, a);
if (charLength == maxlength) {
focusNextComponent();
}
} else {
focusNextComponent();
}
}
private void focusNextComponent() {
if (CustomLengthTextField.this == KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner()) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
}
}
}
}
Just put this code in KeyTyped event:
if ((jtextField.getText() + evt.getKeyChar()).length() > 20) {
evt.consume();
}
Where "20" is the maximum number of characters that you want.
I want to make my j table column to limit character like allowed only 16 character.I tried various methods nothing works.can anybody helps me?.
Here's what I did
The Call:
JTable table = new JTable();
JTextField textField = new JTextField();
limitCharacters(jtf, 16);
table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(jtf));
The limitCharacters Method:
private void limitCharacters(JTextField textField, final int limit) {
PlainDocument document = (PlainDocument) textField.getDocument();
document.setDocumentFilter(new DocumentFilter() {
#Override
public void replace(DocumentFilter.FilterBypass fb, int offset,
int length, String text, AttributeSet attrs)
throws BadLocationException {
String string = fb.getDocument().getText(0,
fb.getDocument().getLength())
+ text;
if (string.length() <= limit)
super.replace(fb, offset, length, text, attrs);
}
});
}
An answer found here https://community.oracle.com/thread/1482301
"Custom Cell Editors
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#validtext
and a custom document on a JTextField
One example worth thousand words"
import java.awt.*;
import javax.swing.*;
public class Test2 extends JFrame {
public Test2() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = getContentPane();
String[] head = {"One","Two","Three"};
String[][] data = {{"R1-C1", "12345678", "R1-C3"},
{"R2-C1", "R2-C2", "R2-C3"},
{"R3-C1", "R3-C2", "R3-C3"}};
JTable jt = new JTable(data, head);
content.add(new JScrollPane(jt), BorderLayout.CENTER);
JTextField jtf = new JTextField();
jtf.setDocument(new LimitedPlainDocument(10));
jt.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(jtf));
setSize(300,300);
}
public static void main(String[] args) { new Test2().setVisible(true); }
}
class LimitedPlainDocument extends javax.swing.text.PlainDocument {
private int maxLen = -1;
/** Creates a new instance of LimitedPlainDocument */
public LimitedPlainDocument() {}
public LimitedPlainDocument(int maxLen) { this.maxLen = maxLen; }
public void insertString(int param, String str,
javax.swing.text.AttributeSet attributeSet)
throws javax.swing.text.BadLocationException {
if (str != null && maxLen > 0 && this.getLength() + str.length() > maxLen) {
java.awt.Toolkit.getDefaultToolkit().beep();
return;
}
super.insertString(param, str, attributeSet);
}
}
I'm using BlueJ, and I have two classes.
public class mainMenu extends JFrame
{
ArrayList<String> one=new ArrayList<String>();
ArrayList<String> zero=new ArrayList<String>();
public static void main(String[] args){
mainMenu m=new mainMenu();
}
public mainMenu(){
JPanel p=new JPanel();
JTextField idOne=new JTextField(4);
DocumentFilter fOne=new LengthFilter();
idOne.getDocument().setDocumentFilter(fOne);
}
}
and
class LengthFilter extends DocumentFilter{
private int max=4;
public void insertString(DocumentFilter.FilterBypass fb, int offset,String text, AttributeSet attr) throws BadLocationException {
if (fb.getDocument().getLength() + text.length() <= max){
fb.insertString(offset, text, attr);
}else {
Toolkit.getDefaultToolkit().beep();
}
}
public void replace(DocumentFilter.FilterBypass fb, int offset, int length,
String text, AttributeSet attr) throws BadLocationException {
if (fb.getDocument().getLength() + text.length() - length <= max){
fb.replace(offset, length, text, attr);
}else {
Toolkit.getDefaultToolkit().beep();
}
}
}
When I try to compile the first class, it comes up with a compiler error:
cannot find symbol - method setDocumentFilter(javax.swing.text.DocumentFilter)
Why and how do I fix this?
setDocumentFilter is undefined for the Document class. You need
DocumentFilter filter = new LengthFilter();
((AbstractDocument)idOneTextField.getDocument()).setDocumentFilter(filter);
when i try to append a char or string to jtextarea after pressing a Specific button , something odd happens , e.g i want to append the '}' after pressing '{' by user in jtextarea , by the following code , the final string in jTextArea would be "}{" instead of being "{}"
private void keyPressedEvent(java.awt.event.KeyEvent evt)
{
if(evt.getkeychar() == '{' )
{
JtextArea1.append("}");
}
}
You should almost never use a KeyListener on a JTextArea or other JTextComponent. For this, I'd use a DocumentFilter which allows you to update the Document before the user's input has been sent to it.
e.g.,
import javax.swing.*;
import javax.swing.text.*;
public class DocFilterEg {
public static void main(String[] args) {
JTextArea textArea = new JTextArea(10, 20);
PlainDocument doc = (PlainDocument) textArea.getDocument();
doc.setDocumentFilter(new DocumentFilter() {
#Override
public void insertString(FilterBypass fb, int offset, String text,
AttributeSet attr) throws BadLocationException {
text = checkTextForParenthesis(text);
super.insertString(fb, offset, text, attr);
}
#Override
public void replace(FilterBypass fb, int offset, int length,
String text, AttributeSet attrs) throws BadLocationException {
text = checkTextForParenthesis(text);
super.replace(fb, offset, length, text, attrs);
}
private String checkTextForParenthesis(String text) {
if (text.contains("{") && !text.contains("}")) {
int index = text.indexOf("{") + 1;
text = text.substring(0, index) + "}" + text.substring(index);
}
return text;
}
});
JOptionPane.showMessageDialog(null, new JScrollPane(textArea));
}
}
I need to not allow any characters to be entered after X have been typed. I need to send a beep after X characters have been typed. I know how to do this after the user presses enter, but I need to do it before the user presses enter. The approach I found from Oracle's site is to add a DocumentSizeFilter to the JTextPane. I can't get this to notify the user when they have gone over (it doesn't work until they press enter). This is a sample of what I have.
public class EndCycleTextAreaRenderer extends JTextPane
implements TableCellRenderer {
private final int maxNumberOfCharacters = 200;
public EndCycleTextAreaRenderer() {
StyledDocument styledDoc = this.getStyledDocument();
AbstractDocument doc;
doc = (AbstractDocument)styledDoc;
doc.setDocumentFilter(new DocumentSizeFilter(maxNumberOfCharacters ));
}
Override the insertString method of the document in the JTextPane so that it doesn't insert any more characters once the maximum has been reached.
For example:
JTextPane textPane = new JTextPane(new DefaultStyledDocument() {
#Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
if ((getLength() + str.length()) <= maxNumberOfCharacters) {
super.insertString(offs, str, a);
}
else {
Toolkit.getDefaultToolkit().beep();
}
}
});
Update:
You can change your class as follows:
public class EndCycleTextAreaRenderer extends JTextPane implements TableCellRenderer {
private final int maxNumberOfCharacters = 200;
public EndCycleTextAreaRenderer() {
setStyledDocument(new DefaultStyledDocument() {
#Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
if ((getLength() + str.length()) <= maxNumberOfCharacters) {
super.insertString(offs, str, a);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
});
}
}
Here is a sample program, for you where, as you enter the fourth time into the TextPane it will beep, without even you pressing the Enter key:
import javax.swing.*;
import javax.swing.text.*;
import java.awt.Toolkit;
public class TextPaneLimit extends JFrame
{
private JPanel panel;
private JTextPane tpane;
private AbstractDocument abDoc;
public TextPaneLimit()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
panel = new JPanel();
tpane = new JTextPane();
Document doc = tpane.getStyledDocument();
if (doc instanceof AbstractDocument)
{
abDoc = (AbstractDocument)doc;
abDoc.setDocumentFilter(new DocumentSizeFilter(3));
}
panel.add(tpane);
add(panel);
pack();
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new TextPaneLimit().setVisible(true);
}
});
}
}
class DocumentSizeFilter extends DocumentFilter {
private int max_Characters;
private boolean DEBUG;
public DocumentSizeFilter(int max_Chars) {
max_Characters = max_Chars;
DEBUG = false;
}
public void insertString(FilterBypass fb
, int offset
, String str
, AttributeSet a)
throws BadLocationException {
if (DEBUG) {
System.out.println("In DocumentSizeFilter's insertString method");
}
if ((fb.getDocument().getLength() + str.length()) <= max_Characters)
super.insertString(fb, offset, str, a);
else
Toolkit.getDefaultToolkit().beep();
}
public void replace(FilterBypass fb
, int offset, int length
, String str, AttributeSet a)
throws BadLocationException {
if (DEBUG) {
System.out.println("In DocumentSizeFilter's replace method");
}
if ((fb.getDocument().getLength() + str.length()
- length) <= max_Characters)
super.replace(fb, offset, length, str, a);
else
Toolkit.getDefaultToolkit().beep();
}
}
Hope this might help.
I would suggest checking the # of characters with every key entered by adding a keyReleasedListener, it is something I used in a recent GUI of mine to check bounds seemingly instantly and display errors to the user as they typed.
Here is how I implemented it on one of my TextFields:
carbonTextField.addKeyListener(new java.awt.event.KeyAdapter()
{
public void keyReleased(java.awt.event.KeyEvent evt)
{
carbonTextFieldKeyReleased(evt);
}
});
Check the following code:
txtpnDesc.addKeyListener(new KeyAdapter() {
#Override
public void keyTyped(KeyEvent e) {
if(txtpnDesc.getText().length() == 30)
{
e.consume();
}
}
});