Is there a way to stop the Robot class after it has started

帅比萌擦擦* 提交于 2021-02-20 02:49:53

问题


Is there a way to stop Java Robot execution once it's started? I have a program that simulates left mouse button clicks, but i also have an unused JButton named STOP that was supposed to stop this clicking that i started using the Robot class. I noticed that Robot is fairly harder than the Thread class. Any ideas?

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.util.Random;

public class Click{
Robot robot = new Robot();

private void leftClick(){
    int no = new Random().nextInt(6) + 1;
    robot.mousePress(InputEvent.BUTTON1_MASK);
    robot.delay(50 * no);
    robot.mouseRelease(InputEvent.BUTTON1_MASK);
    robot.delay(220 * no);
  }

public Click() throws AWTException{
    while (true) {
        leftClick();
        System.out.println("Click");            
    }       
  } 
}

And in the GUI class i have a JButton that looks something like this:

private JButton getBtnStart() {
    if (btnStart == null) {
        btnStart = new JButton("Start");
        btnStart.setBackground(Color.WHITE);
        btnStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    c = new Click();
                } catch (AWTException e1) {
                    e1.printStackTrace();
                }
            }
        });
    }
    return btnStart;
}

回答1:


There are several issues. An unconditional loop in a constructor is a no-go. Apart from that, you are blocking the EDT, so I wonder whether this can work at all.

It's not even clear to me how you want to stop this clicking, given that you can hardly do anything while the robot is doing its job.

However, here is a sketch of how this could probably be solved, based on the information that you provided so far:

import java.awt.AWTException;
import java.awt.GridLayout;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class RobotControlTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final RobotControl robotControl = new RobotControl();

        f.getContentPane().setLayout(new GridLayout(1,2));

        final JButton startButton = new JButton("Start");
        f.getContentPane().add(startButton);

        final JButton stopButton = new JButton("Stop");
        stopButton.setEnabled(false);
        f.getContentPane().add(stopButton);

        startButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                startButton.setEnabled(false);
                stopButton.setEnabled(true);
                robotControl.startClicking();
            }
        });

        stopButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                robotControl.stopClicking();
                startButton.setEnabled(true);
                stopButton.setEnabled(false);
            }
        });

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class RobotControl
{
    private final Random random = new Random();
    private final Robot robot;
    private volatile boolean running = false;

    RobotControl()
    {
        try
        {
            robot = new Robot();
        }
        catch (AWTException e)
        {
            e.printStackTrace();
            throw new RuntimeException(e);
        }        
    }

    void startClicking()
    {
        Thread thread = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                running = true;
                performClicks();
            }
        });
        thread.start();
    }

    void stopClicking()
    {
        System.out.println("Stopping");
        running = false;
    }

    private void performClicks()
    {
        System.out.println("Starting");
        while (running)
        {
            leftClick();
            System.out.println("Clicked");
        }
    }

    private void leftClick()
    {
        int no = random.nextInt(6) + 1;
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(50 * no);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
        robot.delay(220 * no);
      }    
}

EDIT based on the comment:

Of course it is possible to detect mouse movements, and pause the clicking for a while after each mouse movement. However, I don't like the direction where this is going. The first part of the answer was just a quick sketch to illustrate the idea that you could have developed on your own when reading a bit about threads. Any extensions to this sketch are inappropriate. And my gut feeling is that this will end in a chain of further requirements that could, somehow, be kludged into the original answer, but should have been stated right from the beginning.

But I see your problem: "Develop a program that does what I need" is not a valid question.

But to at least anwswer the "implicit" question of "How can I detect a mouse movement?":

You can use MouseInfo.getPointerInfo().getLocation() to obtain the mouse position, and regularly check this point to see whether it is different from the previous point.

Kludged into the original program:

import java.awt.AWTException;
import java.awt.GridLayout;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class ExtendedRobotControlTest
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final RobotControl robotControl = new RobotControl();

        f.getContentPane().setLayout(new GridLayout(1,2));

        final JButton startButton = new JButton("Start");
        f.getContentPane().add(startButton);

        final JButton stopButton = new JButton("Stop");
        stopButton.setEnabled(false);
        f.getContentPane().add(stopButton);

        startButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                startButton.setEnabled(false);
                stopButton.setEnabled(true);
                robotControl.startControl();
            }
        });

        stopButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                robotControl.stopControl();
                startButton.setEnabled(true);
                stopButton.setEnabled(false);
            }
        });

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class RobotControl
{
    private final Random random = new Random();
    private final Robot robot;

    private Thread clickingThread;
    private Thread observingThread;

    private long lastMovementMillis = -1;
    private Point lastMousePosition = null;

    private volatile boolean running = false;

    RobotControl()
    {
        try
        {
            robot = new Robot();
        }
        catch (AWTException e)
        {
            e.printStackTrace();
            throw new RuntimeException(e);
        }        
    }

    void startObserver()
    {
        observingThread = new Thread(new Runnable(){

            @Override
            public void run()
            {
                observeMovement();
            }
        });
        observingThread.start();
    }

    private void observeMovement()
    {
        while (running)
        {
            Point p = MouseInfo.getPointerInfo().getLocation();
            if (!p.equals(lastMousePosition))
            {
                System.out.println("Movement detected");
                lastMovementMillis = System.currentTimeMillis();
                lastMousePosition = p;
            }
            try
            {
                Thread.sleep(50);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
                Thread.currentThread().interrupt();
                return;
            }
        }
    }


    void startControl()
    {
        stopControl();
        System.out.println("Starting");
        lastMovementMillis = System.currentTimeMillis();
        lastMousePosition = MouseInfo.getPointerInfo().getLocation();
        running = true;
        startClicking();
        startObserver();
    }    

    private void startClicking()
    {
        clickingThread = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                performClicks();
            }
        });
        clickingThread.start();
    }

    void stopControl()
    {
        if (running)
        {
            System.out.println("Stopping");
            running = false;
            try
            {
                clickingThread.join(5000);
                observingThread.join(5000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
                Thread.currentThread().interrupt();
            }
        }
    }

    private void performClicks()
    {
        System.out.println("Starting");
        while (running)
        {
            long t = System.currentTimeMillis();
            if (t > lastMovementMillis + 1000)
            {
                leftClick();
                System.out.println("Clicked");
            }
            else
            {
                System.out.println("Waiting before clicks...");
                try
                {
                    Thread.sleep(50);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                    return;
                }
            }
        }
    }

    private void leftClick()
    {
        int no = random.nextInt(6) + 1;
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(50 * no);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
        robot.delay(220 * no);
      }    
}



回答2:


I'd just put the following condition after each robot action: if Esc is pressed then sleep. And at that moment I'd pop up a JOptionPane to the user decide if he wants to abort or continue the process.

I think it's an easier way to do what you want to.



来源:https://stackoverflow.com/questions/24596936/is-there-a-way-to-stop-the-robot-class-after-it-has-started

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!