How to accept SOH character from TextField in JAVAFx - java

I have written simple GUI screen that actually contains a JavaFx textField where the user enters a string and that String I have to pass to TCP client.
Now the problem is user enters a string that contains SOH as the delimiter.
SOH is nothing but "\u001". But when the user enters a String that contains this delimiters then it is removed and only the simple plain text is retrieved. How can I eliminate this. This unique character is very important for me.
For example my string is as follows:
8=FIX.4.2\u001 9=9 \u001 35=A \u001 34=1\u001 49=TTDS68AP
Observer the above String where I have the \u001 character representing SOH. But when I entered this String in the TextField then the result is like:
8=FIX.4.29=9135=A34=149=TTDS68AP
How can I get the SOH character too from the Text Field?

The problem is that javaFX TextField filters invalid characters with the following function:
private static boolean isInvalidCharacter(char c, boolean newlineIllegal, boolean tabIllegal) {
if (c == 0x7F) return true;
if (c == 0xA) return newlineIllegal;
if (c == 0x9) return tabIllegal;
if (c < 0x20) return true;
return false;
}
This happens after you paste and before the String is stored in the field. Before this function is called a custom filter can be set and applied, in this filter you can change SOH to something else; it's unicode representation ␁ is a good candidate:
textField.setTextFormatter(new TextFormatter<>((t) -> {
t.setText(t.getText().replace((char)1, '\u2401'));
return t;
}));
Adding the above will change it after it's pasted and before it's stored. When you want to use the String from the textField you need to replace it back to SOH with:
String withSOH = field.getText().replace('\u2401', (char)1);

I think the problem is that you want to enter by keyboard and see the control character in the text field:
Ctrl-A (SOH) is a known shortcut, and selects the previous character.
The control character will not be displayed in a normal font.
So I came to the following solution:
String SOH_REPR = "°"; // We show SOH as this string.
someTextField.setOnKeyPressed((ke) -> {
if (ke.getCode().getName().equals("A")
&& ke.isControlDown()
&& !ke.isAltDown()
&& !ke.isMetaDown()
&& !ke.isShiftDown()) {
TextField textField = (TextField) ke.getSource();
ke.consume();
int pos = textField.getCaretPosition();
textField.insertText(pos, SOH_REPR);
}
});
someTextField.setOnKeyReleased((ke) -> {
if (ke.getCode().getName().equals("A")
&& ke.isControlDown()
&& !ke.isAltDown()
&& !ke.isMetaDown()
&& !ke.isShiftDown()) {
ke.consume();
}
});
// Convert it back.
String text = someTextField.getText().replace(SOH_REPR, "\u0001");
Pasting text with SOHs would still needed to be done for completeness sake.

Try adding the your encoding as argument.
System.setProperty("file.encoding", "yourEncoding");
I think UTF-8 should work.

Related

Android : Validate half-width Japanese character

This question might have been asked several times but I didn't find a proper answer so I am posting this question. What I want to do is validate the Japanese text entered in the edit text field to allow only half-width Japanese characters. I only want to check the validation once user enters the text and taps on some action button.
I've created method validates if typed character is half-width kana:
public boolean validate(String c) {
Pattern pattern = Pattern.compile("[\uff61-\uff9f]");
return pattern.matcher(c).matches();
}
I understood that you want to check is written text composed of only half-width kana, yes? To do this, in onClick() of button which you clicking for validate, write something like this:
for (int i = 0; i < textToValidate.length(); i++) {
if (validate(textToValidate.charAt(i))) {
continue;
} else {
System.out.println("Text wasn't written in half-width kana.");
return;
}
}
System.out.println("Text was written in half-width kana.");
Let me know if my answer is helpful for you. ;)
Okay so I came across many solutions and this one worked for me.
Basically, I have a Japanese half-width validation regex and compared it to my string.
val halfWidthRegex = "^[ァ-ン゙゚]+\\s?[ァ-ン゙゚]+$"
if(myText?.matches(halfWidthRegex.toRegex()))
// Valid halfwidth text
else // Invalid halfwidth text.

Java: how to allow backspace being pressed in JTextField

I've made a JTextField that restricts characters being entered unless it's numbers, letter "e", or comma . But now I realised that it restricts backspace being pressed to. How can I change it? I'll add the code, where it checks what key is being pressed, below
for (JTextField tf : listOfFields)
{
String value = tf.getText();
int n = value.length();
if (ke.getKeyChar()>= '0' && ke.getKeyChar() <= '9' || ke.getKeyChar() == ','|| ke.getKeyChar() == 'e')
{
tf.setEditable(true);
}
else
{
tf.setEditable(false);
}
}}});
To have a text field accept a numeric entry, you should use a JFormattedTextField:
JFormattedTextField field = new JFormattedTextField(
NumberFormat.getIntegerInstance());
field.setColumns(12);
To make it check both a localized number format (one that uses commas) and also the java.lang syntax (like 1e5), you can create a NumberFormatter which does both:
NumberFormatter formatter = new NumberFormatter() {
#Override
public Object stringToValue(String text)
throws ParseException {
try {
return Double.valueOf(text);
} catch (NumberFormatException ne) {
return super.stringToValue(text);
}
}
};
JFormattedTextField field = new JFormattedTextField(formatter);
field.setColumns(12);
Each field’s value can be retrieved with the getValue method:
for (JFormattedTextField tf : listOfFields) {
Number value = (Number) tf.getValue();
// ...
}
Restricting the keys typed by the user is not the correct way to guarantee numeric entry. For instance, your code would allow a user to type 123,4,45,678.
There are many keys which allow editing. Home, End, Delete, and Ctrl-A are just a few. You shouldn't try to explicitly accommodate them all with a keystroke whitelist. Let JFormattedTextField do the work of verifying the input.
If you really want to stick to this way of filtering, assuming ke is a KeyEvent, test the key code not the key char: add this condition
|| ke.getKeyCode() == KeyEvent.VK_BACK_SPACE

Wrap dynamic text automatically in Jbutton

I have a problem with my Jbuttons.
In my application, you can easily change the ui language and you can easily override the default translations for my buttons.
In this case, it is very unclear how long the text can be in a button, but my buttons have a fixed size (because of graphical harmony and so on).
Now my problem is, that I haven't found a solution to wrap a text with a inner button margin.
Example:
BUTTON 1:
"Hello"
-> Hello is short enough to be printed without newline.
BUTTON 2:
"Hello guys"
-> Due to the html tags, Hello guys will be automatically wrapped in two lines.
BUTTON 3:
"Hello g."
-> Hello g. fills exactly the width of the button. No word wrap by HTML!.
Now, the button 3 itself looks very crappy and overloaded.
Therefore I need a solution to automatically wrap a text which is wider or equal -4px than the button.
Additionally a text which doesn't contain a whitespace, should be wrapped either if it is too long.
A very easy solution for this problem is a utility method, I wrote.
Just call it in your *ButtonUI #paint method before you call super.paint(c,g);
e.g.:
if (c instanceof AbstractButton) {
String txt = button.getText();
button.setText(getWrappedText(g, button, txt));
}
Here is my formatter for free use (and for optimization, too ;) )
private static final String STR_NEWLINE = "<br />";
private FontRenderContext fontRenderContext = new FontRenderContext(new AffineTransform(), true, true);
private String getWrappedText(Graphics graphics, AbstractButton button, String str) {
if( str != null ) {
String text = str.replaceAll("<html><center>", "").replaceAll("</center></html>", "");
int width = button.getWidth();
Rectangle2D stringBounds = button.getFont().getStringBounds(text, fontRenderContext);
if ( !str.contains(STR_NEWLINE) && (width-5) < ((Double)stringBounds.getWidth()).intValue()) {
String newStr;
if( str.contains(" ") ) {
int lastIndex = str.lastIndexOf(" ");
newStr = str.substring(0, lastIndex)+STR_NEWLINE+str.substring(lastIndex);
} else {
int strLength = ((str.length()/3)*2);
newStr = str.substring(0, strLength)+STR_NEWLINE+str.substring(strLength);
}
return newStr;
}
}
return str;
}

Cipher/decipher textArea text using XOR

I have got a code which should cipher text from my textArea with some sort of String key, after the button is pressed down. The problem is, that this method can cipher text using only one character, not the whole string. I need to have a little longer key, so string is needed here. How can I change that?
btnCipher.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent klik) {
String textToCipher = textArea.getText();
String cipherKey = textField.getText();
String cipheredText = "";
int xor;
char temp;
for (int i=0; i<textToCipher.length(); i++){
xor = textToCipher.charAt(i)^cipherKey; //error
temp = (char)xor;
cipheredText += temp;
}
textArea.setText(cipheredText);
}
});
If your strings are in UTF-8 encoding, then using exclusive or between two strings (assume equal length for a moment) may NOT produce a valid UTF-8 result (in particular, you may create a "continuation" character if you have "a" and "æ" in the same position). Look here for a deeper discusion.
What is the use-case that you are trying to handle?
Change that line to:
xor = textToCipher.charAt(i) ^ cipherKey.charAt(i % cipherKey.length);
As mentioned in this post, while String class doesn't really mind storing a string with unpaired surrogates (which is actually invalid for a UTF-16 format), you will run into trouble encoding/decoding the string in other charset and when using code point related methods.

How to filter keys in MIDP TextField?

I have a TextField.PhoneNumber but I would like to filter out "+" character. In other words, I need a new constraint for TextField. Is there a way to define a new constraint with TextField?
How about preventing keys from cycling on a mobile phone within a midp?
It might not what you really want.
But, MIDP does not support change constraint rule as you want. So, I suggest HACK for your purpose.
How about use ItemStateListener to check if text field contains string which you want to filter out and if this string is exist, change text field forcefully.
The code could be looks like below:
// set item state listener
form.setItemStateListener(this);
// check if text field contains invalid string
// then replace it
public void itemStateChanged(Item item) {
if (item == getTextField()) {
TextField t = (TextField)item;
String s = t.getString();
// + is invalid string
int pos = s.indexOf("+");
if (pos != -1) {
t.setString(s.substring(0, pos) + s.substring(pos + 1));
}
}
}

Categories