I have read and understood how the Robot class in java works. Only thing I would like to ask, is how do I press and release the mouse button inside an if statement. For example I would to make a click only if (and right after) the space button is pressed/released. I would use the code:
try {
Robot robot = new Robot();
if (/*insert my statement here*/) {
try {
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (InterruptedException ex) {}
}
} catch (AWTException e) {}
Unfortunately, there isn't a way to directly control hardware (well, in fact there is, but you would have to use JNI/JNA), this means that you can't simply check if a key is pressed.
You can use KeyBindings to bind the space key to an action, when the spacebar is pressed you set a flag to true, when it's released you set that flag to false. In order to use this solution, your application has to be a GUI application, this won't work with console applications.
Action pressedAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
spaceBarPressed = true;
}
};
Action releasedAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
spaceBarPressed = false;
}
};
oneOfYourComponents.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
oneOfYourComponents.getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released");
oneOfYourComponents.getActionMap().put("pressed", pressedAction);
oneOfYourComponents.getActionMap().put("released", releasedAction);
Then, use
try {
Robot robot = new Robot();
if (spaceBarPressed) {
try {
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (InterruptedException ex) {
//handle the exception here
}
}
} catch (AWTException e) {
//handle the exception here
}
As GGrec wrote, a better way to do it would be to execute your mouse press directly when the keyboard event is fired:
Action pressedAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
try {
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (InterruptedException ex) {
//handle the exception here
}
}
};
My suggestion is that you listen for the keyboard event, and when you receive it, you execute your code without the if statement. Add the listener to your canvas, or whatever.
Careful not to recreate the Robot class each time.
new KeyAdapter() {
#Override
public void keyReleased(final KeyEvent e) {
if (e.keyCode == KeyEvent.VK_SPACE)
try {
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (InterruptedException ex) {
}
}
}
Related
So i have this code here, and it quite literally doesn't work and i just don't know why. It doesn't click, doesn't print out anything. My goal is to make the buttons function as switches between two methods of clicking. Right mouse button clicks, and Left mouse button clicks. Can anyone tell me why this doesn't function?
if (rbRightClickRadioButton.isSelected()) {
System.out.println("RMB Clicker");
Robot clicker = null;
try {
clicker = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
clicker.mousePress(InputEvent.BUTTON2_DOWN_MASK);
clicker.mouseRelease(InputEvent.BUTTON2_DOWN_MASK);
Thread.sleep(delay);
try {
clicker = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
clicker.mousePress(InputEvent.BUTTON2_DOWN_MASK);
clicker.mouseRelease(InputEvent.BUTTON2_DOWN_MASK);
} else if (rbRightClickRadioButton.isSelected()) {
System.out.println("LMB Clicker");
Robot clicker = null;
try {
clicker = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
clicker.mousePress(InputEvent.BUTTON2_DOWN_MASK);
clicker.mouseRelease(InputEvent.BUTTON2_DOWN_MASK);
Thread.sleep(delay);
try {
clicker = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
clicker.mousePress(InputEvent.BUTTON2_DOWN_MASK);
clicker.mouseRelease(InputEvent.BUTTON2_DOWN_MASK);
If you want a button to work as a switch between two options, I would rather use checkbox than radiobutton. The main problem your code has right now is the simple fact that you check the same expression in your if statements.
You should either check if the other radiobutton is selected in your else if statement or just assume that if the rbRightClickRadioButton is not selected, then the other one is, and you don't use else if just a simple else.
In my Java Swing application, I have an embedded JxBrowser component. With this, I am building a right click context menu with all the usual commands: copy, paste, back, forward, refresh, and select all.
I am having difficulty with select all. I am able to manually hit ctrl-a to select all but I cannot figure out how to do this programmatically.
I have tried the following with no success:
popupMenu.add(createMenuItem("Select All", new Runnable() {
#Override
public void run() {
getView().grabFocus();
try {
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_A);
robot.keyRelease(KeyEvent.VK_A);
robot.keyRelease(KeyEvent.VK_CONTROL);
} catch (AWTException ex) {
ex.printStackTrace();
}
}
}));
private static JMenuItem createMenuItem(String title, final Runnable action) {
JMenuItem menuItem = new JMenuItem(title);
menuItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
action.run();
}
});
return menuItem;
}
I have found the answer.
browser.executeCommand(EditorCommand.SELECT_ALL);
So I've updated my code with the help of Cruncher, and now the clicker appears to work better. However whilst the while(pressed) loop is running, no other events are called & so it stays running.
public class Function implements NativeMouseListener {
private Robot robot;
private boolean pressed = false;
private boolean skip = false;
public Function()
{
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
}
private void repeatMouse()
{
skip = true;
robot.mouseRelease(InputEvent.BUTTON1_MASK);
while (pressed)
{
System.out.println("pressed while loop " + pressed);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void nativeMouseClicked(NativeMouseEvent nativeMouseEvent) {
}
#Override
public void nativeMousePressed(NativeMouseEvent nativeMouseEvent) {
System.out.println("GG");
if (!(nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)) {
System.out.println("Returned.");
return;
}
if (!Native.get().getData().getEnabled())
{
System.out.println("Isn't enabled.");
return;
}
pressed = true;
repeatMouse();
}
#Override
public void nativeMouseReleased(NativeMouseEvent nativeMouseEvent) {
System.out.println("released");
if (!(nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)) {
System.out.println("Returned 2");
return;
}
if (!skip)
{
System.out.println("pressed " + pressed);
pressed = false;
System.out.println("pressed " + pressed);
} else {
skip = false;
}
}
}
Any idea why the while loop would stop events from being called? Do I need to use multi threading or some of that jazz?
Thank you.
For one, your main method is not included in your code, but I assume it contains the following line(or similar):
new Project()
try {
bot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
while (pressed) {
bot.mousePress(InputEvent.BUTTON1_MASK);
//bot.mouseRelease(InputEvent.BUTTON1_MASK);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Now let's look at this code. When this runs, pressed will be false at the beginning(presumably), and it will just exit and not be running on later clicks.
What you want to do is have your loop started when you register a click. Let's move it into another method
private void repeatMouse() {
bot.mouseRelease(InputEvent.BUTTON1_MASK);
while (pressed) {
bot.mousePress(InputEvent.BUTTON1_MASK);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Now let's call it in your mouse down native hook
#Override
public void nativeMousePressed(NativeMouseEvent nativeMouseEvent) {
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
pressed = true;
System.out.println(pressed);
repeatMouse();
}
}
EDIT:
It appears your other problem is that after the first mouseRelease, the handler will get called from the native library. I have a potential solution for this.
First next to where you define your pressed variable, define a new skipRelease
boolean skipRelease = false;
Then before every call to mouseRelease, first set skipRelease to true. Then change your mouseRelease handler to the following
#Override
public void nativeMouseReleased(NativeMouseEvent nativeMouseEvent) {
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
if(skipRelease) {
skipRelease = false;
return;
}
pressed = false;
System.out.println(pressed);
}
}
I've been trying to create an autoclicker in java using jnativehook.
It works fine, even compiles and runs. My problem is using Thread.sleep to try and add a delay between clicks:
bot.mousePress(InputEvent.BUTTON1_MASK);
Thread.sleep(50);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
If I were to input a delay of 0 it will function fine. But given no delay it will click too fast.
When I add a delay it will click fine but, when I release the trigger key it will keep clicking for a few seconds given the time it's been clicking. A delay of 0 will not do this however.
Full code:
public class App implements NativeKeyListener{
private JPanel panel1;
private JTabbedPane tabbedPane1;
private JButton spoilerButton;
private JSlider slider1;
private JSlider slider2;
//Removed irrelevant code...
static Robot bot;
static {
try {
bot = new Robot();
} catch (Exception e) {
e.printStackTrace();
}
}
static boolean pressed;
public void click() throws InterruptedException {
try {
bot.mousePress(InputEvent.BUTTON1_MASK);
Thread.sleep(50);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (Exception e) {
e.printStackTrace();
}}
#Override
public void nativeKeyPressed(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode()) == "Delete") {
pressed = true;
while (pressed){
try {
click();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}}
#Override
public void nativeKeyReleased(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode())=="Delete"){
pressed=false;
}}
#Override
public void nativeKeyTyped(NativeKeyEvent e) {
}
public static void main(String[] args) {
JFrame frame = new JFrame("Autoclicker");
frame.setContentPane(new App().panel1);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(400,148);
frame.setResizable(false);
try{GlobalScreen.registerNativeHook();
} catch (Exception e){
System.exit(1);}
GlobalScreen.addNativeKeyListener(new App());
}
}
Looks like the method nativeKeyPressed() gets called continuously when you keep pressing the trigger key. This results in several calls to click() method (assuming it's multi threaded) and due to the sleep() between mouse press and release (mouse click is complete when released) this can happen.
Hence you can try two options depending on the root cause:
1. move the sleep() call after mouse released. If the nativeKeyPressed gets called concurrently this won't work.
2. Use a different thread to execute the click() method when trigger is pressed. In this case, you may need to submit a Runnable object to your thread each time with the 'pressed' check and click() call in it. This will ensure it won't run after pressed becomes false.
I have a jbutton which I want, as soon as it's clicked to make an infinite loop of a mouseMove by a robot class. Then, to be stopped when it is clicked again. Problem is in my code when I press it for the first time, it causes the system to freeze and nothing happens when I click it again. I use:
boolean go = false
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
go = !go;
if (go)
jb.setText("Stop!");
else
jb.setText("Start!");
try {
Robot robot = new Robot();
while (go) {
robot.mouseMove(500, 500);
robot.delay(1000);
robot.mouseMove(500, 400);
}
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
Swing is a single threaded environment. This means that if anything should block this thread, Swing will be unable to respond to new events, including paint requests and it will appear that you UI has been frozen...because it has...
Take a look at Concurrency in Swing
The simplest solution might be to spawn a new thread and run your loop within it...
Start by writing a Runnable that handels the work you want done...
public class MouseRunner implements Runnable {
#Override
public void run() {
try {
Robot robot = new Robot();
while (go) {
robot.mouseMove(500, 500);
robot.delay(1000);
robot.mouseMove(500, 400);
}
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
Then when the user first clicks the button, create a Thread and start it...
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
go = !go;
if (go) {
jb.setText("Stop!");
Thread t = new Thread(new MouseRunner());
t.start();
} else {
jb.setText("Start!");
}
}
});
Beware, your go variable is likely going to need to made volatile