Reputation: 31
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
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:
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
Reputation: 46
Try declaring work
as volatile
:
static volatile boolean work = false;
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.
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