How to distinguish the commonly printed keyboard keys from the rest - java

I want to collect keyboard input and append it together in a java StringBuilder, but using LWJGL's Keyboard event, i end up fetching more than I wish, like Shift, CapsLock, Escape, F1 to F12, Enter, even punctuation etc.. These keys also have key ID's, but by appending them, they are printed as a square (unrecognized character i believe).
My goal is to ignore these non-printable keys without having to create a giant array with all these unwanted keys. Is there any way to do so?
P.S. Mind that i wish the common symbols like \,.-< etc. to still be considered into the string, like any text editor would.

Here's an example of what you could use. This example is then used as an inner class and you use it in stead of a regular ActionListener on a component. This example catches the keycode of the event (using KeyEvent). I placed some examples you asked in your questions, I'm sure you'll find more if needed.
You should append a custom string to your existing string in every case of the switch statement.
public class CustomListener extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
try {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_SHIFT:
//Append a string to your existing string
break;
case KeyEvent.VK_F1:
//Append a string to your existing string
break;
case KeyEvent.VK_CAPS_LOCK:
//Append a string to your existing string
break;
case KeyEvent.VK_ENTER:
//Append a string to your existing string
break;
}
}
} catch (NullPointerException e1) {
e1.printStackTrace();
}
}
}

Thanks to Mark W I just found out that the ASCII range from 32 to 126 and 128 to 255 covers, i believe, every single character that is commonly printed in the everyday text-editors. Thanks a bunch :)
Here is a minimal code chunk that might be useful for someone using lwjgl
private StringBuilder text;
private void updateInput()
{
while (Keyboard.next())
{
if (Keyboard.getEventKeyState())
{
// get key info
int key = Keyboard.getEventKey();
char ch = Keyboard.getEventCharacter();
int ascii = (int) ch;
// delete case
if(key == Keyboard.KEY_BACK)
text.setLength(Math.max(0, text.length() - 1));
// append if common char
if((ascii >= 32 && ascii <= 126) || (ascii >= 128 && ascii <= 255))
text.append(ch);
}
}
}

Related

How can I prevent the user from entering the same letter in Hangman JAVA?

I am writing a hangman program and one of the requirements to a hangman game is preventing the user from entering the same letter twice.
I have written the code for that, but the problem is every time I enter a letter it says it is already entered. I need to only say it when it is entered the second time. You guys have any suggestions? I've been trying to fix this for the past few hours, I figured I could ask on here to find some help. I already looked at another Stackoverflow question regarding something similar to this but all those solutions have the same result.
In Java, how can I determine if a char array contains a particular character?
I've tried something like this but it won't work either:
boolean contains = false;
for (char c : store) {
if (c == character) {
System.out.println("Already Entered");
contains = true;
break;
}
}
if (contains) {
// loop to top
continue;
}
SECOND CLASS-
public void hangman(String word, int life) {
KeyboardReader reader = new KeyboardReader();
char[] letter = new char[word.length()];
char[] store = new char[word.length()];
String guess;
int i = 0, tries = 0, incorrect = 0, count = 1, v = 0;
while (i < word.length()) {
letter[i] = '-';
I would just use the String.contains() method:
String aString = "abc";
char aChar = 'a';
return aString.contains(aChar + "");
To keep track of guessed letters you can use a StringBuffer, appending them using a StringBuffer.append() to append new letters (maintaining state) and use the StringBuffer.toString() method to get the String representation when you need to do the comparison above.
Since Java 1.5 the class String contains the method contains(). My idea is to collect all entered letters into a string variable and using above method:
// My code line
String letterAlreadyEntered = "";
// Your code line
char character = reader.readLine().charAt(0);
// My code line
if (letterAlreadyEntered.contains("" + character) == true) {
//Put code here what ever you want to do with existing letter
} else {
letterAlreadyEntered += character;
}
In my opinion, this is an easier way to check for occurrences than in arrays, where you have to write your own check method.

Optimizing text from JTextField based selected buttons

I'm pretty new to java and I have a small issue with my code. The code works pretty well but I feel like it can be improved.
Here's the code:
if(evt.getStateChange()==1){
String value = "-MyAppArgument ";
String temp = CustomARG.getText();
CustomARG.setText(temp+""+value);
}else if(evt.getStateChange()!= 1){
String value = "-MyAppArgument ";
CustDEVARGSargsTextField.setText(CustDEVARGSargsTextField.getText().replace(value,""));
}
I have 4 check box buttons, each has an argument like the one above. My idea of optimizing was to construct a string based on selected buttons and use the string in actual processbuilder, but I'm not sure how can I do that. The question is how can I optimize this, is my idea good?
Another option is, rather than add / remove parameters in response to a checked event, instead completely rebuild the string from scratch in response to each event. Not necessarily "optimized" but you don't really need this to be optimized, you just need it to function and to be maintainable.
For example, pseudo-code (feel free to use a StringBuilder, doesn't really matter):
void updateParameterString () {
String parameterString = ""; // constant params can be initialized here too
if (checkbox1 is checked) parameterString += " -arg1";
if (checkbox2 is checked) parameterString += " -arg2";
if (checkbox3 is checked) parameterString += " -arg3";
if (checkbox4 is checked) parameterString += " -arg4";
CustDEVARGSargsTextField.setText(parameterString); // option: trim the string
}
void onAnyCheckButtonStateChange () {
updateParameterString();
}
Another advantage of this approach is you can e.g. initialize the parameter string text box using the initial default values of the checkboxes with the same code, by, say, setting check states when you create the checkboxes then calling updateParameterString() when the form is displayed.
Other permutations of the above are of course possible, depending on what is most appropriate, e.g. replacing updateParameterString() with a method that just generates and returns the string and using that in the correct places instead.
Nice example from Oracle.
StringBuffer choices;
Four accessory choices provide for 16 different
combinations.
The "choices" StringBuffer contains the string that
indicates the current selection.You can change chars (c,g,h,t) on your symbols for process.Also,if you need postfix like "-MyAppArgument " you could add it,but it must be constant,because we need some fixed indexes to put our values depending on on/off toggle status of checkboxes.
choices = new StringBuffer("cght"); // change it to your postfix
---- //zero accessories
c--- //one accessory
-g--
--h-
---t
cg-- //two accessories
c-h-
c--t
-gh-
-g-t
--ht
-ght //three accessories
c-ht
cg-t
cgh-
cght //all accessories
You could add item listener on all of check boxes:
sampleCheckBox1.addItemListener(this);
sampleCheckBox2.addItemListener(this);
sampleCheckBox3.addItemListener(this);
sampleCheckBox4.addItemListener(this);
Then listen to them and change "choices":
public void itemStateChanged(ItemEvent e) {
int index = 0;
char c = '-';
Object source = e.getItemSelectable();
if (source == sampleCheckBox1) {
index = 0;
c = 'c';
} else if (source == sampleCheckBox2) {
index = 1;
c = 'g';
} else if (source == sampleCheckBox3) {
index = 2;
c = 'h';
} else if (source == sampleCheckBox4) {
index = 3;
c = 't';
}
//Now that we know which button was pushed, find out
//whether it was selected or deselected.
if (e.getStateChange() == ItemEvent.DESELECTED) {
c = '-';
}
//Apply the change to the string.
choices.setCharAt(index, c);
}
Also,if you had constant string just add it above main code,like:
final String = "-MyAppArgument ";

Removing special character without using Java Matcher and Pattern API

I am trying to write one java program. This program take a string from the user as an input and display the output by removing the special characters in it. And display the each strings in new line
Let's say I have this string Abc#xyz,2016!horrible_just?kidding after reading this string my program should display the output by removing the special characters like
Abc
xyz
2016
horrible
just
kidding
Now I know there are already API available like Matcher and Patterns API in java to do this. But I don't want to use the API since I am a beginner to java so I am just trying to crack the code bit by bit.
This is what I have tried so far. What I have done here is I am taking the string from the user and stored the special characters in an array and doing the comparison till it get the special character. And also storing the new character in StringBuilder class.
Here is my code
import java.util.*;
class StringTokens{
public void display(String string){
StringBuilder stringToken = new StringBuilder();
stringToken.setLength(0);
char[] str = {' ','!',',','?','.','_','#'};
for(int i=0;i<string.length();i++){
for(int j =0;j<str.length;j++){
if((int)string.charAt(i)!=(int)str[j]){
stringToken.append(str[j]);
}
else {
System.out.println(stringToken.toString());
stringToken.setLength(0);
}
}
}
}
public static void main(String[] args){
if(args.length!=1)
System.out.println("Enter only one line string");
else{
StringTokens st = new StringTokens();
st.display(args[0]);
}
}
}
When I run this code I am only getting the special characters, I am not getting the each strings in new line.
One easy way - use a set to hold all invalid characters:
Set<Character> invalidChars = new HashSet<>(Arrays.asList('$', ...));
Then your check boils down to:
if(invaidChars.contains(string.charAt(i)) {
... invalid char
} else {
valid char
}
But of course, that still means: you are re-inventing the wheel. And one does only re-invent the wheel, if one has very good reasons to. One valid reason would be: your assignment is to implement your own solution.
But otherwise: just read about replaceAll. That method does exactly what your current code; and my solution would be doing. But in a straight forward way; that every good java programmer will be able to understand!
So, to match your question: yes, you can implement this yourself. But the next step is to figure the "canonical" solution to the problem. When you learn Java, then you also have to focus on learning how to do things "like everybody else", with least amount of code to solve the problem. That is one of the core beauties of Java: for 99% of all problems, there is already a straight-forward, high-performance, everybody-will-understand solution out there; most often directly in the Java standard libraries themselves! And knowing Java means to know and understand those solutions.
Every C coder can put down 150 lines of low-level array iterating code in Java, too. The true virtue is to know the ways of doing the same thing with 5 or 10 lines!
I can't comment because I don't have the reputation required. Currently you are appending str[j] which represents special character. Instead you should be appending string.charAt(i). Hope that helps.
stringToken.append(str[j]);
should be
stringToken.append(string.charAt(i));
Here is corrected version of your code, but there are better solutions for this problem.
public class StringTokens {
static String specialChars = new String(new char[]{' ', '!', ',', '?', '.', '_', '#'});
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Enter only one line string");
} else {
display(args[0]);
}
}
public static void display(String string) {
StringBuilder stringToken = new StringBuilder();
stringToken.setLength(0);
for(char c : string.toCharArray()) {
if(!specialChars.contains(String.valueOf(c))) {
stringToken.append(c);
} else {
stringToken.append('\n');
}
}
System.out.println(stringToken);
}
}
public static void main(String[] args) {
String a=",!?#_."; //Add other special characters too
String test="Abc#xyz,2016!horrible_just?kidding"; //Make this as user input
for(char c : test.toCharArray()){
if(a.contains(c+""))
{
System.out.println(); //to avoid printing the special character and to print newline
}
else{
System.out.print(c);
}
}
}
you can run a simple loop and check ascii value of each character. If its something other than A-Z and a-z print newline skip the character and move on. Time complexity will be O(n) + no extra classes used.
String str = "Abc#xyz,2016!horrible_just?kidding";
char charArray[] = str.toCharArray();
boolean flag=true;;
for (int i = 0; i < charArray.length; i++) {
int temp2 = (int) charArray[i];
if (temp2 >= (int) 'A' && temp2 <= (int) 'Z') {
System.out.print(charArray[i]);
flag=true;
} else if (temp2 >= (int) 'a' && temp2 <= (int) 'z') {
System.out.print(charArray[i]);
flag=true;
} else {
if(flag){
System.out.println("");
flag=false;
}
}
}

Test if two first chars typed in are alphanumeric - no regex

I have following code that needs something smart to deal with typed in chars and detection:
private final MultiWordSuggestOracle mySuggestions = new MultiWordSuggestOracle();
private final Set<String> mySuggestionsData = new HashSet<String>();
#UiHandler("suggestBox")
public void onKeyPress(KeyDownEvent event) {
if (Character.isLetterOrDigit(event.getCharCode())) {
char[] text = suggestBox.getText().trim().toCharArray();
if (text.length != 1) return;
for (char ch : text) {
if (!Character.isLetterOrDigit(ch)) {
return;
}
}
//load data from server into mySuggestionsData
}
}
The question has 3 parts:
How do you test pressed key against alphanumeric chars. Keep in mind this is GWT so I would rather not use regex ( but if there is no other option ...).
What is the best way to detect the length of text typed into the SuggestBox?
Is KeyDownEven the best choise? And why is it triggered twice when any key is pressed?
Instead of handling events, you should make your own SuggestOracle (possible wrapping a MultiSuggestOracle used as an internal cache) and check the query's length and "pattern" there to decide whether to call the server or not (and then give an empty list of suggestions as the response, or maybe a single suggestion being the exact query).
As a side note, I don't understand why you don't want to use a regex; either using the java.lang.String methods taking a regex as a String, or the com.google.gwt.regexp.shared.RegExp class.
1. I'd use KeyPressHandler instead of Up/Down handler.
As far as I understand, you are more interested to get what the user has typed but not the key that was actually pressed on the keyboard. Also, you can use Character.isDigit(c) and Character.isLetter(c) since KeyPressEvent.getCharCode() will return char (c).
2. Likely you want to check text length at some point (e.g. when user presses Enter), then
// handler block
if (c == KeyCodes.KEY_ENTER) {
int length = ((SuggestBox) event.getSource()).getText().length();
// take an action depending on length
}
// handler block continued
should fit.
3. See [1] and perhaps it's browser specific.
Edit: [1],[2] and [3] combined (using KeyUpHandler):
private static final int THREASHOLD = 2;
private String phrase = "";
...
searchBox.addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(KeyUpEvent event) {
String text = ((SuggestBox) event.getSource()).getText();
if (!phrase.equals(text)) {
if (text.length() >= THREASHOLD) {
boolean alphanum = true;
for (int i = 0; i < THREASHOLD; i++) {
char c = text.charAt(i);
if (!Character.isDigit(c) && !Character.isLetter(c)) {
alphanum = false;
break;
}
}
if (alphanum) {
//RPC (won't be called twice)
}
}
phrase = text;
}
}
});

How to validate if Text entered is a numeric number?

I have a calculation application which I need to validate the fields to check if the values entered are numeric numbers and not alphanumeric. I have some ideas about the codes.
Please guide me if I have done anything wrong or seem noob as this is my first time trying out Swing.
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
String text1 = jTextField1.getText(); // TODO add your handling code here:
}
private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {
String text2 = jTextField2.getText(); // TODO add your handling code here:
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if (text1 and text2 != <numeric number>){
JOptionPane.showConfirmDialog(null, "Please enter numbers only", "naughty", JOptionPane.CANCEL_OPTION);
}
// First we define float variables.
float num1, num2, result;
// We have to parse the text to a type float.
num1 = Float.parseFloat(jTextField1.getText());
num2 = Float.parseFloat(jTextField2.getText());
// Now we can perform the addition.
result = num1+num2;
// We will now pass the value of result to jTextField3.
// At the same time, we are going to
// change the value of result from a float to a string.
jTextField3.setText(String.valueOf(result));
// TODO add your handling code here:
}
Please do help. By the way why does my NetBeans keep informing me that it does not recognize the "JOptionPane" Command?
Float.parseFloat() will throw a NumberFormatException if the String isn't numeric and cannot be parsed into a Float. You can add a try-catch block to check for this condition:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
float num1, num2, result;
try {
num1 = Float.parseFloat(jTextField1.getText());
num2 = Float.parseFloat(jTextField2.getText());
result = num1+num2;
jTextField3.setText(String.valueOf(result));
} catch (NumberFormatException e) {
JOptionPane.showConfirmDialog(null, "Please enter numbers only", "naughty", JOptionPane.CANCEL_OPTION);
}
}
If alphanumeric input is not valid for the Swing component in the first place, then instead of validating this post-entry, you should restrict the component to accept only certain format in the first place.
Using the formatters that Swing provides, you can set up formatted text fields to type dates and numbers in localized formats. Another kind of formatter enables you to use a character mask to specify the set of characters that can be typed at each position in the field. For example, you can specify a mask for typing phone numbers in a particular format, such as (XX) X-XX-XX-XX-XX.
That said, you can, among other things, use Integer.parseInt(String s) to see if an arbitrary string can be parsed into an int; the method throws NumberFormatException if it can't. There are also Double.parseDouble, etc.
See also
Java Tutorials/Swing/How to use Formatted Text Field
How to use the Focus Subsystem/Input Validation
Java Tutorials/Internationalization/Formatting - Numbers and Currencies
Related questions
A simple way to create a text field (or such) that only allows the user to enter ints/doubles in Java?
A textbox class only accept integers in Java
Validating an integer or String without try-catch - java.util.Scanner option
try {
Integer.parseInt(foo);
} catch (NumberFormatException e) {
// Naughty
}
Try this:
String temp = txtField.getText();
try
{
int val = Integer.parseInt(temp);
}
catch(NumberFormatException e) {
System.out.println("Invalid");
}
To make it more enjoyable, use JOptionPane (makes it more more interactive)
textFieldCrDays = new JTextField();
textFieldCrDays.addKeyListener(new KeyAdapter() {
//// validate onlu numeric value
public void keyTyped(KeyEvent e) {
if (textFieldCrDays.getText().length() < 3 && e.getKeyChar() >='0' && e.getKeyChar() <= '9')
{
// Optional
super.keyTyped(e);
}
else
{
// Discard the event
e.consume();
}
}
});
A relatively old question, but I figured I would take a shot at it, to maybe help out the random Google Searches.
Another approach someone could take to minimise code and reduce the number of additional classes is to add a KeyListener for the keyType event and check for the Char value. This isn't very portable (you can't use region specific formatting such as numerical punctuation), but this could be quite helpful for straight integers.
You could also do a relative length here as well:
textField.addKeyListener(new KeyAdapter()
{
#Override
public void keyTyped(KeyEvent keyEvent)
{
if (textField.getText().length() < 3 && keyEvent.getKeyChar() >= '0' && keyEvent.getKeyChar() <= '9')
{
// Optional
super.keyTyped(keyEvent);
}
else
{
// Discard the event
keyEvent.consume();
}
}
});
You can also add another event listener to validate the entire integer for further processing (the entire number must be > 800 and < 5220 for example).
A good place for this would be on the focusLost event(?).
If you are doing these features frequently, it would be best to subclass the JTextField class to provide this functionality.
EDIT: Using Character.isLetter(keyEvent.getKeyChar()) is even more clear.

Categories

Resources