I am someone new to Java and working with the robot class. I would like to make an emergency stop function for my robot so when it does something wrong I can make the automation end. While robot so far has been easy the key listener escapes me, please explain in a "my first keylistener" style, thank you!
Here is what I have so far:
public static void keyboard(String input, HWND window) throws Exception {
System.out.println("Keyboard Typing:\n" + input);
//This is just to stop the error, but I don't know how
//to actually listen
KeyEvent e = null;
for (int i = 0; i < input.length(); i++) {;
keepFocus(window);
if(stopBot(e /*How to pass a key press*/) == true){
break;
}
char c = input.charAt(i);
keyboardHandler(c);
Thread.sleep(80);
}
}
public static boolean stopBot(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_END){
return true;
}
return false;
}
There is other code but this is all that is relevant to my problem
The easiest way I could think about implementing a key event is by making your current class extend a Key Listener class. Basically, you want your current class to be listening for keystrokes in the background. You'll start by adding the implementation to your class name:
public YourClassName implements KeyListener {
}
Now, your class is able to listen for key strokes in the background. You'll now need to add a listener in your code and then give it instructions on what to do when hit. You'll add the listener by invoking the following method:
this.addKeyListener()
You can also replace "this" with any other instantiated object capable of handling action events. Now, you just need to be able to instruct the program on what to do when the listener picks up a key stroke event. The key listener will evoke one method from the KeyListener class you are extending: keyPressed(KeyEvent e), keyRelease(KeyEvent e), or keyTyped(KeyEvent e). These are the functions that will then run whatever code you'd like when a key-event is picked up and passed through the function. You will need to override these methods like so:
#Override
public void keyReleased(KeyEvent e) {
//whatever you want to happen in the case of
this event, I assume stop your robot
}
So, as you can see, you don't need to worry about invoking your own KeyEvent, Java's addKeyListener will take care of this as long you've extended the class and given instructions on what to do for each event! Hope this helps!
Related
Hello from novice java developer, I created a MouseListener and MouseAdapter in a thread to control mouse action for mouse pressed, released and drag action. Each action will do specific things but i could not assign each MouseEvent e from each action to a variable.
So, how can deal with this problem? I also wonder if the method parameter MouseEvent e is specific to each method?
Here is my code:
Thread thread = new Thread() {
public void run() {
addMouseListener(new MouseAdapter() {
//#override deleted because i want to use e as a different action.
public void mouseaction(MouseEvent e) {
/* In here i want to control MouseEvent e action
(drag, pressed and released) and do specific things in with e event
and if e changes state should be changed in code during while(true) */
}
}
}
You can get all this information from the mouseEvent by calling the method getModifiersEx(), for example:
int eventType = e.getModifiersEx();
if (eventType & MOUSE_DRAGGED > 0) {
// Code to be executed when mouse is dragged
}
if (eventType & MOUSE_PRESSED > 0) {
// Code to be executed when mouse button is pressed
}
...
Note that the eventType is a bit field where multiple bits can be activated simultaneously.
//#override deleted because i want to use e as a different action.
public void mouseaction(MouseEvent e)
You can't just make up method names. You need to implement the methods of the listener. You need to handle the mousePressed, mouseReleased methods separately. For the mouseDragged you need to implement the MouseMotionListener.
Read the section from the Swing tutorial on Implementing Listener. You can find sections on:
How to Implement a MouseListener
How to Implement a MouseMotionListener
which both contain working examples.
I'll address this concern:
I also wonder if the method parameter MouseEvent e is specific to each method?
Every time this method is invoked by Swing, a new Event is generated. Your #Override annotation makes no difference.
So when user clicks somewhere, a MouseEvent N°2556 is generated for it, and the method is invoked with that event as a parameter.
When user drags the mouse away, a MouseEvent N°2557 is generated, and the method is again invoked with this new event as a parameter.
More broadly: All those MouseEvents will always be different instances. They are immutable, as well.
This means if you want to persist some information for your game loop to see, you need to store the relevant conditions in a field somewhere. And you won't be able to access it from an anonymous class because you won't have a handle to it. Here is a quick and dirty example (shameless reuse of #FrankPuffer's code):
public class MyMouseAdapter extends MouseAdpater {
public boolean isMousePressed = false; // This info is persisted here
public void mouseaction(MouseEvent e) { // This is only triggered upon user input
int eventType = e.getModifiersEx();
if (eventType & MouseEvent.MOUSE_PRESSED) {
isMousePressed = true;
}
if (eventType & MouseEvent.MOUSE_RELEASED) {
isMousePressed = false;
}
}
}
public static void main(String[] argc){
// Before the game loop:
MyMouseAdapter myAdapter = new MyMouseAdapter();
jpanel.addMouseListener(myAdapter);
// In the game loop
while(true) {
if(myAdapter.isMousePressed) { // This info is available anytime now!
// Do something
}
}
}
I am trying to have a window pop up when key 1 is pressed and a separate window when key 2 is pressed.
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_1)
{
TicTacToeDriver tic = new TicTacToeDriver();
PointCounter();
}
else if(e.getKeyCode() == KeyEvent.VK_2)
{
HangmanDriver hang = new HangmanDriver();
PointCounter();
}
}
public void keyReleased(KeyEvent e)
{
//do nothing
}
public void keyTyped(KeyEvent e)
{
//do nothing
}
The tic tac toe and hangman games were created by two separate people and the programmers created their own driver.
Solution:
I am assuming that the programmers are familiar with java oriented programming...
Thus, You would just create a new object of one of the games.
Hangman h = new Hangman();
or
Tick h = new Tick();
Tick.start() //depending on their code.
If you are running a Jframe...
you would need to
(insert object name).setVisible(true);
Since you mentioned that they have drivers I assume that they use main methods instead of constructors even though the code you provided creates objects of the classes.
Thus, when the button is clicked or key is pressed.. Just call the main method of the driver class.
hangman.main(null); //this is a terrible way to do it btw.
I also recommend using KeyBindings API instead of keylistener as keybindings does not require focus... which could also be problem.
Another problem would be..
this.addKeyListener(this);
You have to add the keylistener to the component.
But, this is where problems arise as you are using keylistener.. Your JComponent that you added the KeyListener to might not have focus. Thus, the action wont fire till the component has focus and an action is triggered.
I want to be able to receive input from the keyboard by the user but I've added everything I thought would allow my program to do this and still it does not work. What am I doing wrong?
class KeyInput implements KeyListener {
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed");
}
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased");
}
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped");
}
}
public GameView() {
this.addKeyListener(new KeyInput());
}
The constructor works fine and KeyInput is an inner class of the GameView object.
When running the game, if I press a key nothing gets printed to the system output.
Am I missing something? Thanks!
KeyListener is fickle mistress, it wants a lot of attention all the time. Basically, it will only raise key events if the component it is registered to has focus AND is focusable.
Generally, you want to avoid using it and use key bindings API instead, How to Use Key Bindings, but this will depend on whether you MUST use pure AWT APIs or not....
my big problem is that i am codding a game.i have 2 player in a jframe that they can play cuncurrent. first player play with arrow keys and second with w/a/s/d keys..my instrutor said me that to achieve cuncurrent play i should instantiate two thread that every thread manage its own special player..noe i am confuse that how i can have two thread for tow players that only diffrence between them is the key that they listen...
another question that maybe can help me is can i have a listener that listen only some special keys??for exampe i new a listener that only listen w/s/a/d buttuns??(i am familiar with keyevent.getkeycode but it is not my mean because i want a listener that never listen another keys this is listen all keys and in decision choose codder favorite key)
i will be infinitively greatfull if you help me.
You can define your own keys processors like this (mainFrame is JFrame instance)
ActionMap actions = ((JComponent)mainFrame.getContentPane()).getActionMap();
InputMap inputs = ((JComponent)mainFrame.getContentPane()).getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
Action a=new AbstractAction() {
public void actionPerformed(ActionEvent e) {
//call your action code here
}
};
actions.put("myAction", a);
inputs.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK), "myAction");
before that don't forget to set Focus to the JPanel before listening KeyListener check KeyBindings for extended funcionalities, here is very usefull infos about Listeners in Swing
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
myPanel.grabFocus();
myPanel.requestFocus();//or requestFocusinWindow()
}
});
A key listener will listen to all keys. You just have to react to the ones you need. Since you can have any number of key listeners, there is no issue in having a key listener per player.
The keyListener listens to all keys pressed.
But inside the code you can check which key is pressed, if ignore it if it is not one of the keys that you want to react to. In fact, you could use the same class for both listeners and just pass the key that each of them has to react to as parameters.
Having said that, you should not need two threads for it. I understand two threads to avoid the GUI freezing (a thread for managing the GUI, another for doing the calculations of positions). Of course, being it homework, it can be asked this way just so get to learn the basic concepts of threading.
Ok so heres how i would do it, i would have 2 classes, one called game and the other player, game extends your JFrame and player implements your keyListener, In game you could have 2 instances of Player, one for the instance that uses the D-keys and the other would use asdw or whatever, heres an example:
public void keyPressed(KeyEvent e)
{
switch(playerNumber)
{
case PLAYER_1:
if(e.getKeyCode==VK_UP)
{
//do some code for an "up event"
}
if(e.getKeyCode==VK_DOWN)
{
//do some code for a "down event"
}
if(e.getKeyCode==VK_LEFT)
{
//do some code for a "left event"
}
if(e.getKeyCode==VK_RIGHT)
{
//do some code for a "right event"
}
break;
case PLAYER_2:
if(e.getKeyCode==VK_W)
{
//do some code for an "up event"
}
if(e.getKeyCode==VK_S)
{
//do some code for a "down event"
}
if(e.getKeyCode==VK_A)
{
//do some code for a "left event"
}
if(e.getKeyCode==VK_D)
{
//do some code for a "right event"
}
break;
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public static final int PLAYER_1 = 0;
public static final int PLAYER_2 = 1;
all you would have to do is tell the player instance if its player1 or player2, which would be easy, if you need any more examples or anything let me know, ive made plenty of hotseat games (games where more than 1 person are playing on 1 computer).
I have the following snippet of code, changeTextArea is a TextArea object.
changeTextArea.addKeyboardListener(new KeyboardListenerAdapter()
public void onKeyPress( Widget sender, char keyCode, int modifier){
//do something
//I WISH TO STOP THE EVENT THAT MAPS TO THIS KEYPRESS FROM BUBBLING ANY FURTHER
}
}
How would I stop the Event that is causing this method to be called from bubbling up from changeTextArea into the Panels/Widgets/Composites/Whatever that contain changeTextArea. Put succinctly, how do I stop it from bubbling any further. Any help would be appreciated (especially code samples).
As far as I know you can't do it via a keyboard listener, but it is possible by adding an event preview using the DOM class:
DOM.addEventPreview(EventPreview preview)
Then when you get the event:
onEventPreview(Event event)
You should return false, to say you want to cancel the event. The Event object also supports this method:
public final void cancelBubble(boolean cancel)
Cancels bubbling for the given event. This will stop the event from being propagated to parent elements.
You can find more details here:
http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/index.html?overview-summary.html
You can definitely use the Event's cancelBubble() and preventDefault() methods from within any code that has access to the Event. There's no need to have an event preview...
You can call the sender's cancelKey() event. Here's an example that will only allow numbers to be inputted, all other keys get rejected.
private class RowColChangeHandler implements KeyPressHandler
{
public void onKeyPress(KeyPressEvent event) {
char keyCode = event.getCharCode();
if(keyCode <48 || keyCode >57)
{
((TextArea)event.getSource()).cancelKey();
}
}
}
you could reach it when possible by doing
event.doit = false