Macijke
Macijke

Reputation: 31

Java robot does not stop

I have a problem with the operation of the JNativeHook library and Java Robot. My robot should run when I press F9 and it should stop when I click F6, but it is not working. I don't know what I am doing wrong here. Every time I tried to stop the robot it just does not stop. The code says that when I press F6 the work value should change to false and the while loop should stop calling the robot.

import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.NativeHookException;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main extends JFrame implements NativeKeyListener {

    static int szerokosc = 2;
    static int dlugosc = 10;
    static boolean work = false;
    static Robot robot;
    static JTextField t1;
    static JTextField t3;
    static JTextField p1;
    JFrame jf;
    JLabel label, label2, label4;

    public Main() {
        try {
            robot = new Robot();
            jf = new JFrame();
            ImageIcon img = new ImageIcon("pickaxe.png");
            JTextPane tp = new JTextPane();
            jf.setLocation(800, 300);
            tp.setFont(new Font("Arial", 0, 32));
            jf.setTitle("Kopacz by Macijke");
            jf.setIconImage(img.getImage());
            jf.setPreferredSize(new Dimension(350, 350));
            jf.setLayout(new FlowLayout());
            label = new JLabel("Kliknij F9, aby włączyć kopanie na 6/3/3!");
            label.setBounds(50, 10, 250, 20);
            jf.add(label);

            label2 = new JLabel("Komenda nr 1");
            label2.setBounds(10, 20, 250, 90);
            t1 = new JTextField("/repair");
            t1.setBounds(100, 50, 150, 30);
            label2.setVisible(true);

            label4 = new JLabel("Długość");
            label4.setBounds(10, 240, 250, 90);
            t3 = new JTextField("10");
            t3.setBounds(65, 270, 50, 30);

            // ============
            p1 = new JTextField("11");
            p1.setBounds(255, 50, 30, 30);

            // ============

            jf.setDefaultCloseOperation(3);
            jf.setLayout(null);
            jf.add(t1);
            jf.add(t3);
            jf.add(label2);
            jf.add(label4);
            jf.add(p1);
            jf.pack();
            jf.setVisible(true);
        } catch (AWTException var3) {
            var3.printStackTrace();
        }
    }


    public static void main(String[] args) {
        try {
            GlobalScreen.registerNativeHook();
            Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
            logger.setLevel(Level.ALL);
            logger.setUseParentHandlers(false);
        } catch (NativeHookException e) {
            e.printStackTrace();
        }

        GlobalScreen.addNativeKeyListener(new Main());
    }

    @Override
    public void nativeKeyPressed(NativeKeyEvent e) {
        //
    }

    @Override
    public void nativeKeyReleased(NativeKeyEvent e) {
        if (e.getKeyCode() == NativeKeyEvent.VC_F6) {
            work = false;
        }

        if (e.getKeyCode() == NativeKeyEvent.VC_F9) {
            dlugosc = Integer.parseInt(t3.getText());
            work = true;
            int i = 1;
            while (work) {
                robot.mousePress(InputEvent.BUTTON1_MASK);
                for (int z = 0; z < dlugosc; z++) {
                    robot.keyPress(KeyEvent.VK_W);
                    robot.delay(210);
                    robot.keyRelease(KeyEvent.VK_W);

                }

                for (int a = 0; a < szerokosc; a++) {
                    robot.keyPress(KeyEvent.VK_A);
                    robot.delay(150);
                    robot.keyRelease(KeyEvent.VK_A);
                }

                for (int z = 0; z < dlugosc; z++) {
                    robot.keyPress(KeyEvent.VK_S);
                    robot.delay(210);
                    robot.keyRelease(KeyEvent.VK_S);

                }

                for (int z = 0; z < szerokosc; z++) {
                    robot.keyPress(KeyEvent.VK_D);
                    robot.delay(150);
                    robot.keyRelease(KeyEvent.VK_D);
                }
                robot.mouseRelease(InputEvent.BUTTON1_MASK);

                if (i % 25 == 0) {
                    robot.delay(100);
                    robot.keyPress(KeyEvent.VK_2);
                    robot.keyRelease(KeyEvent.VK_2);
                    robot.delay(250);
                    robot.mousePress(InputEvent.BUTTON3_MASK);
                    robot.delay(4000);
                    robot.mouseRelease(InputEvent.BUTTON3_MASK);
                    robot.delay(250);
                    robot.keyPress(KeyEvent.VK_1);
                    robot.keyRelease(KeyEvent.VK_1);
                    robot.delay(100);
                }
                i++;
            }
        }


    }

    @Override
    public void nativeKeyTyped(NativeKeyEvent e) {
        //
    }

}

Upvotes: 3

Views: 240

Answers (2)

Noe Lozano
Noe Lozano

Reputation: 1

I am new on create responses, be nice, please.

I create a Java Swing app using awt.Robot, jnativehook and clipboard. On my first try I got the same problem, when Robot enter in a cycle, jnativehook don't detect ket activity, so, my solution was:

  1. Create a swing main java app with activities
  2. Create a thread for nativehook since constructor
  3. Create a second thread for awt.Robot when swing detect play button activities

With this strategy I can stop Robot via Stop button or from ESC key release

public jRobotWindows(String[] args) throws Exception
{
    jnativehook = new Thread(new jNativeHookThread());
....

and for Robot

public void Play() throws Exception
{
    rThread = new Thread(new RCBH1_0_0());
    rThread.start();
}

and in Robot thread put all my program in run

Upvotes: 0

Try declaring work as volatile:

static volatile boolean work = false;

The problem is probrably due to synchronization

When your method nativeKeyReleased is invoked, it is going to run on a different thread, and all variables visible to a thread are instead copies.

Your code does not work because when you set work as true, this change will not propagate to the copy your while loop is looking at.

The volatile keyword will ensure that this variable is written to the main memory as well, instead of the CPU cache. thus achieving synchronization among different threads.

This article describes well how volatile works in Java.

Side Note

If you need to set the value of work in different locations, you should use synchronized setter method instead of a volatile field, as stated here

The rule of thumb is:

Use Volatile when you variables are going to get read by multiple threads, but written to by only one thread

Use Synchronized when your variables will get read and written to by multiple threads

Upvotes: 0

Related Questions