PDA

View Full Version : Program works, but doesn't


SKG_Scintill
06-5-2012, 07:34 AM
I was trying to make a program that whenever I cause a KeyEvent, the program "presses" the left key, causing me to type backwards in an unorthodox way.


package start;

import java.awt.Robot;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

public class Main {
public static void main(String[] args) throws Exception{
@SuppressWarnings("unused")
abstract class AL implements ActionListener{
public void actionPerformed(KeyEvent e) throws Exception {
Robot r = new Robot();
if(e.isActionKey()){
r.keyPress(KeyEvent.VK_LEFT);
r.keyRelease(KeyEvent.VK_LEFT);
}
}
}
}
}


The code shows no errors, but whenever I run it, it runs for a fraction of a second, then terminates.
I can't figure it out, my teacher can't figure it out. HALP

Edit: Yes I know Username, I'm using Robot again, don't mock me :P

Hakulyte
06-5-2012, 08:34 AM
Question for you, how do you know the program didn't press/release left arrow ?

I see Robot and I see the r. before keyPress etc. but there's really nothing else to add?

trumaestro
06-5-2012, 08:42 AM
I'm not a java guy, but wouldn't you want a loop in there somewhere? I don't see one, but I'm not familiar with java..

SKG_Scintill
06-5-2012, 09:49 AM
Question for you, how do you know the program didn't press/release left arrow ?

I see Robot and I see the r. before keyPress etc. but there's really nothing else to add?

I know it didn't press left, since I had my cursor on the code somewhere, and it didn't go left :P

I'm not a java guy, but wouldn't you want a loop in there somewhere? I don't see one, but I'm not familiar with java..

Yes, the loop is basically what I already tried to prevent my making this class to only trigger upon a key event, otherwise it waits for one.
That being said, I can not tell whether it is waiting for the input or not. Given the length of the run, I can assume it doesn't, but it's not certain.

UserNameGoesHere
06-5-2012, 09:55 AM
I've not seen @SuppressWarnings before. That's new to me.

Why is your AL class abstract? Also why are you defining that class within the main function of your other class?

--edit--
Also, even if this worked correctly wouldn't it cause a sort of infinite loop? Considering you register an event listener for keyboard events, yet within that listener you trigger just such an event?

--edit2--
In your keypress-testing code, also check to make sure the key pressed is NOT left and, if it is, then skip the simulated left key press. That should remove such an infinite loop from there.

You can't directly use abstract classes. Abstract means it doesn't fully implement everything and needs to be extended before being used. Change the abstract keyword to public, remove the suppression of warnings, and if it tells you some method or other needs to be implemented, you can always implement do-nothing methods which merely do nothing and/or call super (if applicable) and then return.

And I don't know why you're making a class-within-a-class.

SKG_Scintill
06-5-2012, 10:10 AM
I've not seen @SuppressWarnings before. That's new to me.
It has no practical purpose, it just gets rid of yellow underscoring.
Why is your AL class abstract?
Otherwise I had to make my KeyEvent a variable, which I would have to validate, which would cause a NullPointerException error. It was an issue I had before.
Also why are you defining that class within the main function of your other class?
ActionListener goes hand-in-hand with actionPerformed. ActionListener waits for input, actionPerformed reacts to the input. From what I've heard, it makes the Listener a loop, but the Performed an "if"-method in the loop. Something which I undoubtly NOT program myself :P
--edit--
Also, even if this worked correctly wouldn't it cause a sort of infinite loop? Considering you register an event listener for keyboard events, yet within that listener you trigger just such an event?
I was basically going for an infinite loop (as said with the ActionListener), until I terminate the program myself.

UserNameGoesHere
06-5-2012, 10:26 AM
Well what I mean is, even if the program worked, you would essentially lose control over your keyboard and get infinite left arrow presses as soon as you pressed any key. That is probably not what you intended. The reason for this is the press which is simulated within the listener would itself trigger the listener which would then resimulate another press which would trigger the same listener again, etc... You need to check to see if the left arrow key is the one which is pressed and, if so, skip over the "simulate left arrow press" instructions.

SKG_Scintill
06-5-2012, 10:38 AM
True, it's good that you foresee that, quite resemblant to my previous problem with Robot, I'll continue fumbling tomorrow.

I tried using KeyTyped instead of KeyEvent, but obviously that won't work, given that KeyTyped is a subclass of KeyEvent.
I'll try making another body around the "if" using KeyTyped, but I don't see much hope in that.

UserNameGoesHere
06-5-2012, 08:50 PM
Here's what I think you should do.

First off, I'm not sure if your teacher is teaching you to use the class-within-a-class thing or not but that's a very non-Java way of doing things. It should be used sparingly, if ever. You just really never see this sort of thing with Java code. Get rid of the Main wrapper class because I don't see that it's doing anything useful and stick your public static void main within your AL class.

Within actionPerformed, either do an additional check (in addition to e.isActionKey()) to make sure the key that is pressed is not the left key. Alternately, instead of that, you could check if a flag is set, and, if not, set the flag and simulate the left key press, then unset the flag. Or something along those lines.

And in your main function you could just use an infinite loop I think. Something like while(true){}. You just need to kill your program using, for example, Windows Task Manager if you do it that way. Alternately in your main function, in a while loop, check if a flag is set and, if so, exit program. And in your actionPerformed, set that flag if a particular key is pressed (Say, the Escape key for example).

qqwref
06-5-2012, 09:32 PM
Yeah, you definitely need some kind of infinite loop, or maybe some kind of window that will sit there and keep the program open until it's closed. Right now the program is basically creating the objects, hitting the end of the main function, and exiting immediately.

PS: Are you required to use Java for this? If not, AutoHotKey would probably be more useful.

SKG_Scintill
06-6-2012, 12:30 AM
Nah, it's not required, the main project at school is finished, we're all just trying to kill time.
@Username: I'll have to carefully read that post word by word.

SKG_Scintill
06-6-2012, 07:33 AM
So far it doesn't close immediately, I made a safety thread.sleep in case the robot goes looping (which it probably will eventually).

I changed the ActionEvent into a KeyEvent, that was an obvious mistake solved, seemed so simple a solution.

It's probably my lack of knowledge when it comes to "abstract"-classes, but it says KL is never used locally. I understand it says that, but I don't know how to solve it :P
Well this is what I have now:
package start;

import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Main {
public static void main(String[] args){
while(true){
abstract class KL implements KeyListener{
public void keyTyped(KeyEvent e){
if(e.isActionKey()){
try {
Robot r = new Robot();
Thread.sleep(1000);
r.keyPress(KeyEvent.VK_LEFT);
r.keyRelease(KeyEvent.VK_LEFT);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}
}
}
}

qqwref
06-6-2012, 06:40 PM
The abstract class KL ...{} clause only *defines* the class. If you want to actually listen to keys, you would basically want to create an instance of a KeyListener subclass, and then attach it to something so that the key events get sent to it.

Also, note that you can't actually create an instance of an abstract class, although you can define subclasses of it. I don't think you want the class to be abstract in this case.

UserNameGoesHere
06-7-2012, 01:46 AM
What qqwref said. The abstract keyword defines an incomplete class. You would first need to define another class that extends that class and create an object of the extending class. You could then cast it to the abstract class. It basically means you're making a class but not implementing all the methods and some extending class will finish implementing the methods.

If it makes more sense, you can think of an abstract class as kind of a cross between a class and an interface except you use the 'extends' rather than 'implements' keyword with it.

Also, as qqwref said, you need to create an object, and you may or may not need to first register the listener with something.

--edit--


package start;

import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KL implements KeyListener{
private boolean inhibitKeyPress;
private Robot r;
public KL(){
super();
inhibitKeyPress = false;
}
public static void main(String[] args){
KL kl = new KL();

//Insert any needed registration code here

while(true);
}
public void keyTyped(KeyEvent e){
if(e.isActionKey() && !inhibitKeyPress){
try {
inhibitKeyPress = true;
r = new Robot();
r.keyPress(KeyEvent.VK_LEFT);
r.keyRelease(KeyEvent.VK_LEFT);
} catch (Exception e1) {
e1.printStackTrace();
} finally {
inhibitKeyPress = false;
}
}
}
}

I don't have a compiler with me right now, but your code should look more something along those lines than what you have. Start with that, and fix up anything that needs fixing from there (for example, I don't know if you need to first register that listener with something or not. If it needs, it, you'll need to enter the registration code where my comment suggests.)