0

I was playing around in Java and trying to make an autoclicker just as a challenge for myself. I was making key bindings to turn it on and off when I discovered that I needed to turn off a while loop from a different class. Normally I would think this to be easy but I am using actions, so the action keeps playing until it is broken. I thought about it for a little bit and came to the conclusion that I needed to ask for a keybind within an action, but I have no idea how to do this. Here is my code right now if you want to help me make some improvements

package autoclicker;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Autoclicker {
    
    JFrame frame;
    JLabel label;
    boolean endis;
    Action enableAction;
    
    public Autoclicker() {
        frame = new JFrame("Autoclicker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(420, 420);
        frame.setLayout(null);
        
        label = new JLabel();
        label.setBackground(Color.red);
        label.setBounds(100, 100, 100, 100);
        label.setOpaque(true);
        
        enableAction = new EnableAction();
        
        label.getInputMap().put(KeyStroke.getKeyStroke("UP"), "enableAction");
        label.getActionMap().put("enableAction", enableAction);
        
        frame.add(label);
        
        frame.setVisible(true);
    }
    
    public class EnableAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {
            endis = true;
            try {
                Robot robot = new Robot();
                while(endis) {
                    robot.mousePress(InputEvent.BUTTON1_MASK);
                    robot.mouseRelease(InputEvent.BUTTON1_MASK);
                }
            } catch (AWTException e1) {
                e1.printStackTrace();
            }
        }
    }
}
CJendantix
  • 23
  • 7
  • Don't use a while loop in an ActionListener. That will block the EDT and prevent the GUI from repainting itself. Instead use a Swing Timer. When you click the button you start the Timer. When you click again you stop the Timer. – camickr Nov 27 '21 at 15:49
  • Ok, but this would be a better answer then a comment, I don't know how to use the Swing Timer. Still, thanks for the help! – CJendantix Nov 27 '21 at 15:50
  • I added it as a comment since I didn't provide any code. When you solve the problem you can post your code as an answer – camickr Nov 27 '21 at 15:52
  • Could you give a link or something so I could learn about the Swing Timer please. :) – CJendantix Nov 27 '21 at 15:58
  • I just typed "Swing timer" in the search box at the top of this page and found lots of examples. You should also keep a link to the [Swing tutorial](https://docs.oracle.com/javase/tutorial/uiswing/TOC.html) handy for tutorials on all Swing basis. – camickr Nov 27 '21 at 16:04

1 Answers1

0

Assuming you want to use your autoclicker on other programs besides the java application, this isn't an easy thing to do. Java Swing was only designed to get events (such as keyboard presses) from the window that's currently focused on. However, according to MasterID on this stack overflow post, it is possible with this library: https://github.com/kwhat/jnativehook. I haven't used this library myself though.

I've made my own auto clicker a long time ago, and here's how I dealt with exiting the loop. Mouse Position is something that is easy to get in Java. MouseInfo.getPointerInfo().getLocation(); So, rather than breaking on a keypress (requiring JFrame focus in Swing), you can break on if the mouse has been moved. In your loop, if the mouse is ever not in the same position, that means it has been moved, so exit the loop. Perhaps something like this:


    public void mainLoop() {
        // Sleep for an amount of time to get mouse into proper position
        Thread.sleep(4000);
        ...
        Point p = MouseInfo.getPointerInfo().getLocation();
        int lastX = (int)p.getX();
        int lastY = (int)p.getY();
        while(!isMoved(lastX, lastY)) {
            // Do Click or other Stuff...
        }
    }

    /** Returns true if the last x and y position don't match the current mouse x and y position on the screen. False if same position. */
    public boolean isMoved(int lastX, int lastY){
        Point p = MouseInfo.getPointerInfo().getLocation();
        return (int)p.getX() != lastX || (int)p.getY() != lastY;
    }

This breaks out of the loop if the mouse is ever moved. And if you want to use Robot.mouseMove(), you could make a simple wrapper class for Robot to handle updating the last position for you.

Dmich
  • 130
  • 6