Escape character in JTextfield - java

I was wondering if there's a simple way to deal with escape characters in a JTextField. The thing is that getText() will escape the escape character. Of course, that will be the preferred behavior most of the time, but not if you want to allow the users to freely provide a delimiter for a CSV file (including \t). Any ideas?
Bob

You can always override the behavior of any and all public functions in a swing component. Its called "specialization". For example, you can create your own MyJTextField class and override the getText() method.

JTextField is only a View so it always has a model inside it, this model is Document class. You can try this:
JTextField f = new JTextField();
// your JTextField is being filled somehow with text ...
Document document = f.getDocument();
try {
String text = document.getText(0, document.getLength());
} catch (BadLocationException ex) {
}
Maybe when you collect text from Document instance instead of JTextField instance it won't be escaped;

I know this may be kind of late for you, but I found an easy solution to that problem:
JTextfield field = new JTextField();
/*someone puts a string into it*/
escapeFulString = field.getText().replace("\\t","\t");
System.out.println(escapeFulString);
This will print out that string with all the tabs. To add any other escape sequences just do that same process.
Just don't forget, java string methods DO NOT edit in place, e.g.:
text.replace("\\t","\t")
//is not the same as
text = text.replace("\\t","\t");

Related

How do I add a list of user inputs into a textfield

Basically assume I have two text fields on my java applet:
[__________] [___________]
The first text field takes in user input and the second textbox prints that user input to store it as a list. So if the user inputted "cat" then "dog", then "frog", the second textfield should look like this:
[cat, dog, frog]. When the user types a word and clicks button 1 it should add the word into the second textfield. The code below is what I tried but nothing is happening:
textf = user input field
texty = output field
public void actionPerformed(ActionEvent e){
if (e.getSource() == b1 ){
x = textf.getText();
texty.add(x);
textf.setText(null);
}
Is this a Swing GUI? Are those JTextFields?
You need to look at the Java API since you're using an inappropriate method, add(...) in your code, and I'd be very surprised if your code with your use of the add method will even compile, since the add method is used for adding other GUI Components to the container that is calling the method, and that's not what you're trying to do.
You're trying to append text, and for that you will need to get the text from the 2nd text field, using getText() add the new String to this text using String concatenation (basically using the + operator, and then set the text of the 2nd text field with the new String using setText(...).
Myself, I'd display the accumulated texts in a JList or JTextArea and not a 2nd JTextField.
So if the user inputted "cat" then "dog", then "frog", the second textfield should look like this: [cat, dog, frog].
Then you need to insert the text into the Document of the text field:
So assuming you create the second JTextField with code like:
JTextField textField2 = new JTextField("[]");
You need to insert text before the "]". So you would insert the text into the Document of the second text field:
String text = textField1.getText() + ",";
Document doc = textField2.getDocument();
doc.insertString(text, doc.getLength() - 1, null);

JTextPane losing styling just after the text is displayed

I have a thread which functions as follows: characters are continuously entered, which are being stored in a StringBuilder. The contents of this string builder need to be styled according to some codes. As the character is appended in the string builder, I have a loop that splits this into an array of strings, and does some processing. Here is small (but complete in itself processing):
SimpleAttributeSet set = new SimpleAttributeSet();
if(string.contains(code1)){
str = string;
int index = string.indexOf(code1);
string = string.replaceAll(code1, "");
StyleConstants.setForeground(set, Color.GREEN);
// data is a another variable of string builder
data.append(string);
i = sb.indexOf(string);
String st = string.substring(index);
doc.setCharacterAttributes(data.indexOf(st), st.length(), set, true);
}
//similarly there are checks and styling for other codes
//terminalArea is of JTextPane type
terminalArea.setText(dataToShow.toString());
The text is colored correctly according to the codes, But as the data is displayed, the colors appear for an instant, and then lost. After that that, when a key is pressed, the colors appear again, but as the key is released, they lost.
I tried terminalArea.repaint(), but nothing happens.
Update:
With respect to StanislavL's answer, Here is what I am having now:
doc = new DefaultStyledDocument();
if(string.contains(code)){
str = string;
int index = string.indexOf(code);
string = string.replaceAll(code, "");
StyleConstants.setForeground(set, Color.GREEN);
dataToShow.append(string);
i = sb.indexOf(string);
String st = string.substring(index);
doc.setCharacterAttributes(dataToShow.indexOf(st), st.length(), set, true);
doc.insertString(doc.getLength() , string, null);
}
//after all conditions
terminalArea.setDocument(doc);
Though the color persists, but only that text is shown colored, which was colored last. The previous ones are shown in white.Please note, the whole string is not colored, only a part of it is colored.
Solved:
StanislavL's answer solved the problem. I overlooked this thing that I was setting the character attributes first, then inserting the array. Interchanging the position solved the issue.
I assume you use StyledEditorKit.
terminalArea.setText(dataToShow.toString());
The code just erases all you have and readd the text to the document. In fact in the document remove(0, docLength) is called and then insertString(theToStringResult) replaces all the styled.
I would recomment to create a new Document instance, insert all the texts with styled using insertString() where you can pass your attributes (or call insertString() just once and the call multiple times setCharacterAttributes()). After the Document instance is ready just call terminalArea.setDocument(theDocumentInstance); rather than setText();

How to use JFormattedTextfield to accept names like strings?

What will be the FormatterFactory's factor value in JFormattedTextField if I only want to accept letters and spaces.
Cause I want it to accepts Names only. Like - John Doe.
I couldn't find an elegant way using a formatter. The non-elegant way is to create a MaskFormatter with the main issue that you will be limiting the number of characters allowed (although you can limit to an arbitrarily large number).
MaskFormatter mask = new MaskFormatter("*************"); // Specifies the number of characters allowed.
mask.setValidCharacters("qwertyuiopasdfghjklzxcvbnm" +
" QWERTYUIOPASDFGHJKLZXCVBNM "); // Specifies the valid characters: a-z, A-Z and space.
mask.setPlaceholderCharacter(' '); // If the input is less characters than the mask, the space character will be used to fill the rest. Then you can use the trim method in String to get rid of them.
JFormattedTextField textField = new JFormattedTextField(mask);
I feel that validating the input is a better approach than restricting characters in this case. I can add an example if you want to use this approach.
Edit: Using InputVerifier, you have to subclass it and override verify as shown below.
JTextField textField = new JTextField();
textField.setInputVerifier(new InputVerifier() {
#Override
public boolean verify(JComponent input) {
String text = ((JTextField) input).getText();
if (text.matches("[a-zA-Z ]+")) // Reads: "Any of a-z or A-Z or space one or more times (together, not each)" ---> blank field or field containing anything other than those will return false.
return true;
return false;
}
});
The text field will not yield focus (except to parent components) until requirements are met.

get and write line with some number

I need to get certain line from text component with multiline support. So it either JTextArea or JTextPane.
How to get line 1 , 2 or .. etc? For example get line3 from text below
line1
line2
line3
line4
And is it possible to set another value for some line? For examp. set lineNew instead of line2
line1
lineNew
line3
line4
Is there any way?
To grab the text in a JTextComponent, use the getText() method which will return a String.
Then to get the lines, split the string on \n.
JTextArea txt = new JTextArea("line1\nline2\nline3\nline4");
String s = txt.getText();
String[] lines = s.split("\n");
// now to access the second line, use lines[1]
Now if you want to modify the text, you can use the setText(String) method.
txt.setText("something else");
There are also a few other methods that you can use to change the text like insert(String,int), append(String), and replaceRange(String,int,int). All of this is documented in the javadocs.
You can use JTextArea#replaceRange to replace a certain line.
For retrieving a certain line I am not completely sure, but I think that the JTextArea#getLineCount, JTextArea#getLineStartOffset, JtextArea#getLineEndOffset should allow you to quickly extract a certain line from the text. Or as tskuzzy already suggested, retrieve the complete text and split it yourself
How to get line 1 , 2 or .. etc?
Get the text from JTextArea / JTextPane by JTextArea.getText() / JTextPane.getText(). Once you have the text as string you can get the different lines by splitting the text with the new line character as a separator.
JTextArea jText = new JTextArea("line1\nline2\nline3\nline4");
String temp = jText.getText();
String[] tempArr = temp.split("\n");
// Method to getText
public String getText(int lineNos){
return Str[lineNos].getText();
}
// Method to setText
public void setText(int lineNos){
Str[lineNos].setText("Hello"); // Can also use Scanner here
}

How do I set the value of a JFormattedTextField with a placeholder character?

I have a formatted text field for ip address:
ipmask = new MaskFormatter("###.###.###.###");
ipmask.setPlaceholderCharacter(' ');
field = new JFormattedTextField(ipmask);
field.setValue("111.222.333.444"); works but
field.setValue(" 10.222.333.444"); does not work
field.setValue("10 .222.333.444"); does not work
field.setValue("10.222.333.444"); does not work
What is the right way to set the value?
Rather odd, but this came up in another question (at Java: network settings window). After digging around turns out there is a RegexFormatter implementation from Sun (see http://java.sun.com/products/jfc/tsc/articles/reftf/; download the source code at http://java.sun.com/products/jfc/tsc/articles/reftf/RegexFormatter.java) which you can use like this:
JFormattedTextField ipAddress;
try{
RegexFormatter ipmask = new RegexFormatter("\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}");
ipmask.setOverwriteMode(false);
ipAddress = new JFormattedTextField(ipmask);
}catch(Exception e1){
}
ipAddress.setValue("255.255.255.255");
You've probably moved on from here, but thought I'd stick this in just in case someone else wanders along.
spaces don't count as numbers (#) and the . count as anything. unfortunately you wont be able to match an IP address with the MaskFormatter unless you can find a way to have multiple MaskFormatters for 1 JFormattedTextField.
simpler
if (field.getValue().matches("[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}")) //do something
EDIT: you'll have to use a regular JTextField and validate it
I've tried to use the mask formatter but its not good with our situation here so i've come up with this method using Regex and instant validation for the user input.
This code is generated using gui builder:
jFormattedTextField2 = new javax.swing.JFormattedTextField();
jFormattedTextField2.setHorizontalAlignment(jFormattedTextField2.CENTER);
jFormattedTextField2.addCaretListener(new javax.swing.event.CaretListener() {
public void caretUpdate(javax.swing.event.CaretEvent evt) {
jFormattedTextField2CaretUpdate(evt);
}
});
Here on every field update the input will be validated using matcher:
private void jFormattedTextField2CaretUpdate(javax.swing.event.CaretEvent evt) {
// validation happen here and the text is red if IP is invalid
final String regex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
final Pattern pattern = Pattern.compile(regex);
String ip = jFormattedTextField2.getText();
Matcher m = pattern.matcher(ip);
jFormattedTextField2.setForeground(Color.red);
if (m.matches()) {
jFormattedTextField2.setForeground(Color.black);
}
}

Categories