Java: Implementing a new thread, now my code executes twice - java

I asked another question the other day about getting keyboard input while within a swing GUI--actually MCR input. One user found a low-level keyboard hook someone wrote. Very cool, and it mostly works. I had to learn some new things to implement it (always happy to do that), and tbh I may not be fully understanding what's going on.
Thing is, and I'll post the code below, it now runs through a while loop (while success == false, in CardRead.java) twice when I implement the thread for the keyboard hook. If I hard code sample data it only runs through once. If I delete the keyboard hook and use a normal Scanner.nextLine() (which means I have to click in the console to provide input to the application), it only runs through once. Start a new thread with an observer for keyboard input? Twice. I don't understand why, or how to fix it. I'd be happy with just understanding exactly what's going on-- if one of you all show me how to fix it, I'll be ecstatic.
Here's the code:
CardRead.java
public class CardRead {
public static String raw_card_data;
int readcount = 1;
String[] tracks = new String[2];
String[] tracks_final = new String[2];
public static void main()
{
// This doesn't happen until after card is swiped, dunno why.
//GUI.outputArea.setText(GUI.outputArea.getText() + "\n\n Scan card \n");
boolean success = false;
while (success == false)
{
//raw_card_data = "%test?;testing?"; // <-- using this, runs thru once
// using THIS, runs through twice.
// create an event source - reads from stdin
final KB_EventSource evSrc = new KB_EventSource();
// create an observer
final KB_RespHandler respHandler = new KB_RespHandler();
// subscribe the observer to the event source
evSrc.addObserver( respHandler );
// starts the event thread
Thread kb_thread = new Thread(evSrc);
kb_thread.start();
// sleep until card swiped
while (raw_card_data == null)
{
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
System.out.println(raw_card_data);
// Tokenize raw_card_data
StringTokenizer tokenizer = new StringTokenizer(raw_card_data, "?");
int i = 0;
do
{
tracks[i] = tokenizer.nextToken();
System.out.println(i + ": " + tracks[i]);
i++;
}
while (tokenizer.hasMoreTokens());
//System.out.println(track1);
//System.out.println(track2);
tracks_final[0] = tracks[0].substring(1,tracks[0].length());
if (tracks[1] != null)
{
tracks_final[1] = tracks[1].substring(1,tracks[1].length());
}
if ( (readcount <= 5) && ( (tracks_final[0].equals("E") || tracks_final[0].equals(null) ) || (tracks_final[1].equals("E") || tracks_final[1].equals(null)) ) )
{
GUI.notout.setText("Card Read Unsuccessful. Scan Again.");
GUI.outputArea.setText(GUI.outputArea.getText() + "Card read unsuccessful. Scan again. \n");
success = false;
readcount++;
}
else if (readcount <= 5)
{
GUI.notout.setText("Card Successfully Read");
GUI.outputArea.setText(GUI.outputArea.getText() + "\n Success! \n");
GUI.outputArea.setText(GUI.outputArea.getText() + "Track 1 = " + tracks_final[0] + "\n");
GUI.outputArea.setText(GUI.outputArea.getText() + "Track 2 = " + tracks_final[1] + "\n");
success = true;
} // end if else chain
} // end while success == false
} // end public void main
} // end class CardRead
KB_RespHandler.java
import java.util.Observable;
import java.util.Observer;
public class KB_RespHandler implements Observer
{
private String resp;
public void update (Observable obj, Object arg)
{
if (arg instanceof String)
{
resp = (String) arg;
CardRead.raw_card_data = resp;
}
}
}
KB_EventSource.java
import de.ksquared.system.keyboard.*;
import java.util.Observable;
public class KB_EventSource extends Observable implements Runnable
{
public static String temp = "";
public static String output = "";
public void run()
{
new GlobalKeyListener().addKeyListener(new KeyAdapter()
{
#Override public void keyPressed(KeyEvent event)
{
switch(event.getVirtualKeyCode())
{
case KeyEvent.VK_0:
if (event.isShiftPressed() == true)
temp += ")";
else if (event.isShiftPressed() == false)
temp += "0";
break;
case KeyEvent.VK_1:
if (event.isShiftPressed() == true)
temp += "!";
else if (event.isShiftPressed() == false)
temp += "1";
break;
/*insert processing for other keys here*/
case KeyEvent.VK_SPACE:
if (event.isShiftPressed() == true)
temp += " ";
else if (event.isShiftPressed() == false)
temp += " ";
break;
case KeyEvent.VK_RETURN:
/*if (event.isShiftPressed() == true)
temp += "\n";
else if (event.isShiftPressed() == false)
temp += "\n";*/
setChanged();
notifyObservers(temp);
//clearChanged();
break;
} // end switch (event.getVirtualKeyCode())*/
} // end public void keyPressed
});
while(true)
try
{
Thread.sleep(100);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}
So, I don't know what's going on. I was thinking maybe I need to stop the thread kb_thread after receiving input, but I can't find any way to do that. thread.stop() and thread.destroy() are deprecated and Eclipse and Google tell me not to use them. And that might not even be what I need to do anyway.

The comment in "CardRead.java" says "which upon success will change success = true".
Does this mean that it might fail, so it won't change success?
If that's true then raw_card_data would still be non-null, and it would try again.
I'm assuming that you resetting raw_card_data to null again at some point.
On another point, this:
if (event.isShiftPressed() == true)
temp += ")";
else if (event.isShiftPressed() == false)
temp += "0";
can be simplified to:
if (event.isShiftPressed())
temp += ")";
else
temp += "0";

Related

Return statement not sending value to display

My return statement is not working while all values up until the get statement (i.e. the set, variables, etc) are working, if forced to a value the display works.
if (Pasta.isChecked() && Pork.isChecked() && Tomato.isChecked() && Carrots.isChecked() && TomatoPaste.isChecked()) {
// RecipeCodes recipe1 = new RecipeCodes();
//recipe1.setRecipeCode(1);
setRecipeCode(1);
getRecipecode();
//Recipecode = 1;
Log.i("INTERNAL CHECK", "RCODE ~" + Recipecode);
break;
public void setRecipeCode(int C) {
Recipecode = C;
Log.i("SETRECIPECODETEST", "RECIPE CODE ~ " + Recipecode);
}
public int getRecipecode(){
return Recipecode;
}
Here is my code for the class that displays based on the "RecipeCode" variable
Recipes temp = new Recipes();
RecipeCodes RDisplay = new RecipeCodes();
//temp.getRecipeCode();
if(temp.getRecipecode() == 1){
RDesc.setText("Italiano Sausage");
//Log.i("WITHINIF","RCODE INTERNAL ~ " + temp.getRecipeCode());
} else {
RDesc.setText("test");
//Log.i("TEST","RCODE WITHIN DISPLAY ~ " + RDisplay.getRecipeCode());
}
(I've done a lot of editing and commenting out of lines so if there's minor syntax errors my bad).
This works:
class Recipe {
private int recipecode;
public void setRecipeCode(int c) {
recipecode = c;
}
public int getRecipecode() {
return recipecode;
}
public static void main(String[] args)
{
Recipe temp = new Recipe();
temp.setRecipeCode(1);
System.out.println(temp.getRecipecode());
}
}

Java parse a string using a scanner, and using the parsed string as input in an if else statement

Hello fellow programmers! I am a Java beginner and I need some help.
I have a program that I want to make the Turtle move using prefabricated instructions in a string called "rule". I want that rule to be parsed into a readable format for an if-else statement. The if-else statement will then read every character in the parsed "rule", and make the Turtle move accordingly to each condition.
I have ran into some issues with the program, it parses (I think so) and displays the rule, but there is no movement from the turtle. I believe it has something to do with the if-else statement. Please help!
import java.awt.*;
import java.util.Scanner;
class FractalEngine
{
World worldObj = new World();
Turtle m = new Turtle(200, 200, worldObj);
Scanner in = new Scanner(System.in);
FractalEngine()
{
//String rule = "F-F+F+F-FQ";
String rule = "F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-FQ";
//String rule = "F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-F-F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-F+F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-F+F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-F-F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-FQ";
m.setHeading(0);
Scanner scanner = new Scanner(rule);
System.out.println();
System.out.println("Fractal Rule: ");
System.out.println(scanner.nextLine());
System.out.println();
// it prints it to the terminal, but no Turtle movement. Am I using the right parsing method?
do
{
Scanner scanRule = new Scanner(rule);
scanRule.nextLine();
if(rule.equalsIgnoreCase("F"))
m.forward(25);
else if(rule.equals("-"))
m.turnLeft();
else if(rule.equals("+"))
m.turnRight();
else
rule = "Q";
}
while(!rule.equalsIgnoreCase("Q"));
System.out.println("Fractal construction terminated.");
}
}
public class FractalConstructor
{
public static void main(String[] args)
{
FractalEngine fe = new FractalEngine();
}
}
I tried that script, and it works for me it prints each action depends on the command , So I think the problem is in your functions I mean (m.forward(), m.turnRight()...)
public class Main {
public static void main(String[] args)
{
String rule = "F-F+F+F-F-F-F+F+F-F+F-F+F+F-F+F-F+F+F-F-F-F+F+F-FQ";
int i = 0 ;
char[] cmds = rule.toCharArray();
do
{
if(cmds[i] == 'F') {
System.out.println("Foward");
}
else if(cmds[i] == '-') {
System.out.println("Left");
}
else if(cmds[i] == '+') {
System.out.println("Right");
}
else // it's surely "Q"
break ;
i++ ;
}
while(true);
System.out.println("Fractal construction terminated.");
}
}
I think you have a lot of code logic issues, you may change your do while loop with code bellow
boolean done = false;
String line ;
while((line = scanner.nextLine()) != null && !done)
{
for (int i = 0; i< rule.length(); i++) {
if(rule.charAt(i) == 'F')
m.forward(25);
else if(rule.charAt(i) == '-')
m.turnLeft();
else if(rule.charAt(i) == '+' )
m.turnRight();
else{
done = true;
break;
}
}
}

Waiting for a Bukkit Task to Complete in a For Loop

I need some serious help.
Here is my code right now.
for (String line : commandStrings) {
line = line.trim();
line = line.replaceAll("\\{PLAYERNAME\\}", target.getName());
util.log(line);
char[] lineArray = line.toCharArray();
if (lineArray.length > 1) {
if (lineArray[0] == '/') {
String command = util.removeElt(lineArray, 0);
util.log(command);
if (!(config.getBoolean("Command Strings." + args[2] + ".delay.firstExecuteDelay")) && count == 0) {
consoleExecuteTask = getTask(command);
BukkitTask task = scheduler.runTask(this.plugin, consoleExecuteTask);
continue;
} else {
consoleExecuteTask = getTask(command);
BukkitTask task = scheduler.runTaskLater(this.plugin, consoleExecuteTask, (delay * 20L));
util.log("ran later");
continue;
}
} else {
util.log("Invalid Command : \" " + String.valueOf(lineArray) + " \" in Command String: " + args[2]);
continue;
}
} else {
continue;
}
}
sender.sendMessage(prefix + ChatColor.GREEN + "Command String : " + args[2] + "Executed.");
return true;
What it is supposed to do, is get a String list from the config with commands to run and a delay between each of them.
Here is the config for that part,
preset2:
delay:
global_delay: true
global_delayString: "10s"
firstExecuteDelay: true
commands:
- "/effect {PLAYERNAME} speed 30 5"
- "/effect {PLAYERNAME} 16 30 5"
When I run the command for the second preset. The problem is that it doesnt wait for the first command to be executed before it moves on to the second commnand in the for loop. How do i make it wait for the first command to be done without freezing the main thread. Here is the important section of the runnable :
public consoleExecuteTask(CommandStrings plugin, String command) {
this.plugin = plugin;
this.command = command;
plugin.getLogger().info("called");
running = true;
}
public void run() {
plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(),command);
running = false;
plugin.getLogger().info("ran " + command);
}
Im am using this method to get the task.
public static consoleExecuteTask getTask(String line) {
if (consoleExecuteTask == null) {
consoleExecuteTask = new consoleExecuteTask(plugin, line);
}
return consoleExecuteTask;
}
You need to use a Scheduler.
To create a scheduler, you need to create a new BukkitRunnable, then run it:
new BukkitRunnable() {
#Override
public void run() {
// Execute the commands here one by one.
}
}.runTaskTimer(mainInstance, 0, delayBetweenCalls);
http://wiki.bukkit.org/Scheduler_Programming

How do I run a (pseudo)main method with an applet?

I'm a beginner/intermediate java programmer that is attempting to code something that is "out-of-my-league". The program is supposed to judge a boxing/MMA match in real time by pressing keys that correspond to different scoring values. I've figured out that I need a KeyListener, and the only way I've found to use that is with an applet.
The problem I've run into is the only cues I have to print out a score come from keyPresses and keyReleases. I want the score to print EVERY second, along with the time. I'm made a clock function and can print every second using another class with a main method, but I don't know how to do this in the applet.
Here's what I have so far:
import java.applet.Applet;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.*;
public class KeyPressTwo
extends Applet
implements KeyListener{
private long t;
private ArrayList<Integer> keysDown = new ArrayList<Integer>();
private double controlOnlyValue = 1; //Stores the score per second for control only
private double threateningValue = 2.5; //Score for threatening with strikes, i.e. landing sig strikes, or sub attempts
private double damagingValue = 4; //Score for doing significant damage and dominating hea
private static double redTotal = 0; //Stores fighter score
private static double blueTotal = 0;
private static boolean firstRun = true;
private static boolean start = false;
private static boolean releasePressed = false; //Tells KeysReleased method when to wipe keysDown list
private static long roundBeganAt = 0; //System time when the round began 5
private static String redName;
private static String blueName;
public void init(){
this.addKeyListener(this);
//If names aren't hardcoded in, get them when the program is run
if (redName == null){
redName = JOptionPane.showInputDialog("Enter the red corner fighter's name.");
blueName = JOptionPane.showInputDialog("Enter the blue corner fighter's name.");
}
}
public void paint(){
setSize(500,500);
}
#Override
public void keyPressed(KeyEvent e) {
if(!keysDown.contains(e.getKeyCode()))
keysDown.add(e.getKeyCode());
//Starts the timer, don't print anything until started
if(keysDown.contains(KeyEvent.VK_SPACE)){
start = true;
roundBeganAt = System.currentTimeMillis();
}
//If it's been more than 1s
if(nextStep()){
//If space has been pushed
if(start){
if(keysDown.contains(KeyEvent.VK_Z) || keysDown.contains(KeyEvent.VK_NUMPAD1)){
redTotal += controlOnlyValue;
}
if(keysDown.contains(KeyEvent.VK_X) || keysDown.contains(KeyEvent.VK_NUMPAD4)){
redTotal += threateningValue;
}
if(keysDown.contains(KeyEvent.VK_C) || keysDown.contains(KeyEvent.VK_NUMPAD7)){
redTotal += damagingValue;
}
if(keysDown.contains(KeyEvent.VK_COMMA) || keysDown.contains(KeyEvent.VK_NUMPAD3)){
blueTotal += controlOnlyValue;
}
if(keysDown.contains(KeyEvent.VK_M) || keysDown.contains(KeyEvent.VK_NUMPAD6)){
blueTotal += threateningValue;
}
if(keysDown.contains(KeyEvent.VK_N) || keysDown.contains(KeyEvent.VK_NUMPAD9)){
blueTotal += damagingValue;
}
System.out.print("\n" +redName +": " +redTotal +" \t" +blueName +": " +blueTotal +"\t\t" +time());
releasePressed = true;
}
}
}
//Prints time since start (e.g. 2:05)
private static String time() {
String minutes = "";
String seconds = "";
int sRaw; //Gets time directly from system, will go above 60
int s; //Gets time from sRaw, (0 - 59)
sRaw = (int)((System.currentTimeMillis() - roundBeganAt))/1000;
s = sRaw%60;
minutes = Integer.toString(sRaw/60);
if(s < 10)
seconds = "0" +Integer.toString(s);
else seconds = Integer.toString(s);
return minutes +":" +seconds;
}
//Returns true if it's been more than1s since the last time it ran
public boolean nextStep() {
if(firstRun){
t = System.currentTimeMillis();
firstRun = false;
return true;
}
if(System.currentTimeMillis() > t + 1000){
t = System.currentTimeMillis();
return true;
}else
return false;
}
public void printList(){
for(int i : keysDown)
System.out.print(i +" ");
System.out.println();
}
#Override
public void keyReleased(KeyEvent e) {
if(releasePressed){
keysDown.clear();
releasePressed = false;
}
}
#Override
public void keyTyped(KeyEvent e) {
}
}
Maybe something along these lines would work for you:
Thread timerOutputThread = new Thread(new Runnable(){
public boolean running = true;
public void run(){
output();
}
private void output(){
try {
Thread.sleep(1000);
} catch(Exception ex) {
ex.printStackTrace();
}
System.out.println("PRINT THE SCORE HERE");
if(running){
output();
}
}
});
timerOutputThread.start();
Stick that code wherever you want the Thread timer to be started, and then fill in that spot where it says "PRINT THE SCORE HERE".
I've figured out that I need a KeyListener,.."
Or preferably key bindings.
..and the only way I've found to use that is with an applet.
Where on Earth did you hear that?!? It is definitely wrong. Start using a JFrame for this app. and it will work better because focus will be more reliable.

How do I check if a class' return of a method equals null?

In my program, I have a while loop that will display a list of shops and asks for an input, which corresponds with the shop ID. If the user enters an integer outside the array of shops, created with a Shop class, it will exit the loop and continue. Inside this loop is another while loop which calls the sellItem method of my Shop class below:
public Item sellItem()
{
displayItems();
int indexID = Shop.getInput();
if (indexID <= -1 || indexID >= wares.length)
{
System.out.println("Null"); // Testing purposes
return null;
}
else
{
return wares[indexID];
}
}
private void displayItems()
{
System.out.println("Name\t\t\t\tWeight\t\t\t\tPrice");
System.out.println("0. Return to Shops");
for(int i = 0; i < wares.length; i++)
{
System.out.print(i + 1 + ". ");
System.out.println(wares[i].getName() + "\t\t\t\t" + wares[i].getWeight() + "\t\t\t\t" + wares[i].getPrice());
}
}
private static int getInput()
{
Scanner scanInput = new Scanner(System.in);
int itemID = scanInput.nextInt();
int indexID = itemID - 1;
return indexID;
}
The while loop in my main class method is as follows:
boolean exitAllShops = true;
while(exitAllShops)
{
System.out.println("Where would you like to go?\nEnter the number which corresponds with the shop.\n1. Pete's Produce\n2. Moore's Meats\n3. Howards Hunting\n4. Foster's Farming\n5. Leighton's Liquor\n6. Carter's Clothing\n7. Hill's Household Products\n8. Lewis' Livery, Animals, and Wagon supplies\n9. Dr. Miller's Medicine\n10. Leave Shops (YOU WILL NOT BE ABLE TO RETURN)");
int shopInput = scan.nextInt();
if(shopInput >= 1 && shopInput <= allShops.length)
{
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(allShops == null)
{
System.out.println("still null"); // Testing purposes
leaveShop = false;
}
}
}
else
{
System.out.println("Are you sure you want to leave?\n1. Yes\n2. No");
int confirm = scan.nextInt();
if(confirm == 1)
{
exitAllShops = false;
}
}
The problem is here:
boolean leaveShop = true;
while(leaveShop)
{
allShops[shopInput - 1].sellItem();
if(allShops == null)
{
System.out.println("still null"); // Testing purposes
leaveShop = false;
}
}
No matter what I do, I can't get "still null" to print to confirm that I'm correctly calling the return statement of the method sellItem of the class Shop. What am I doing wrong?
After calling allShops[...].sellItem(), allShops is still a valid array reference -- there's no way it could be null! You probably want to test the return value from sellItem:
if(allShops[shopInput-1].sellItem() == null)

Categories