Reputation: 513
So I'm making a program which utilizes a Robot to copy and paste text. However, I've hit a wall when it comes to how to stop the Robot in the middle of its actions (I prefer using a button since the whole application is in a GUI). Right now I have it so that the Robot is created and starts when a different button is clicked, and it stops after a certain amount of messages. From what I understand you need to stop the thread it's on, but I'm not sure how to do that.
public void initSpam() throws AWTException
{
Robot bot = new Robot();
isRunning = true;
int delayTime;
if(isDefault)
delayTime = DEFAULT;
else
delayTime = customTime;
StringSelection selection = new StringSelection(spam);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, selection);
bot.delay(1250);
for (int i = 0; i < buffer; i++) {
bot.keyPress(KeyEvent.VK_CONTROL);
bot.keyPress(KeyEvent.VK_V);
bot.keyRelease(KeyEvent.VK_CONTROL);
bot.keyRelease(KeyEvent.VK_V);
bot.keyPress(KeyEvent.VK_ENTER);
bot.keyRelease(KeyEvent.VK_ENTER);
bot.delay(delayTime);
}
}
The above is the method that's called when the other JButton is pressed. If anyone could guide me how to do this and explain how all of this threading works/how to work with it properly (assume I don't know much), I'd greatly appreciate it. Thank you!
Upvotes: 0
Views: 523
Reputation: 18320
If you need to continuously execute a series of repeating actions, javax.swing.Timer
is the way to go:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Main {
private static final Timer timer = new Timer(1000, Main::run);
public static void main(final String[] args) {
final JFrame frame = new JFrame();
frame.setLayout(new FlowLayout());
frame.setMinimumSize(new Dimension(200, 200));
final JButton startButton = new JButton("start");
startButton.addActionListener(e -> timer.start());
frame.add(startButton);
final JButton stopButton = new JButton("stop");
stopButton.addActionListener(e -> timer.stop());
frame.add(stopButton);
frame.setVisible(true);
}
private static void run(final ActionEvent e) {
System.out.println("do stuff");
}
}
You should not call sleep
or delay
or they will make your button unresponsive. The delays should be only controlled by Timer
object.
If your action is more complex and you need sleeps/delays in random places, it might be easier to create new thread:
private static Thread thread;
public static void main(final String[] args) {
...
startButton.addActionListener(e -> {
thread = new Thread(Main::run);
thread.start();
});
stopButton.addActionListener(e -> thread.interrupt());
}
private static void run() {
try {
while (true) {
Thread.sleep(1000);
System.out.println("do stuff");
}
} catch (final InterruptedException e) {
return;
}
}
Each time you call Thread.sleep
from your worker thread it will throw InterruptedException
if the main thread interrupted it.
Keep in mind, that you cannot interact with most of AWT components from your new thread. Even if you want to change a text on a label you have to do that through SwingUtilities.invokeAndWait
. You should also not share any mutable state between those threads - unless properly synchronized. Stick with the first option, even if it slightly complicates your code - not having to deal with threads is usually worth it.
Upvotes: 1
Reputation: 599
Thread workThread=new Thread(new Runnable() {
@Override
public void run() {
//WORK initspam here
}
});
to stop work, on click call:
workThread.interrupt();
in the initSpam add:
for (..) {
if (Thread.interrupted()) {
break;
}
}
Upvotes: 1