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);
}
}
Related
I know time and time again people have asked how to start a thread after it's been stopped and everyone says you can't. This isn't a duplicate to that because I've found no solution for the problem.
private void runInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
while (running) {
try {
checkPixel();
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
public void nativeKeyPressed(NativeKeyEvent e) {
// TODO Auto-generated method stub
System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
if(NativeKeyEvent.getKeyText(e.getKeyCode()).equals("F9")){
stop();
}
else if(NativeKeyEvent.getKeyText(e.getKeyCode()).equals("F10")){
}
So in my code I'm listening for global key events using JNativeHook. I can successfully stop the checkPixels() using the F9 key but I'm not understanding what I should do using F10 when I wanna start up checkPixel() again.
checkPixel() basically checks for a change in pixel color
ANSWERED Added an if statement for my state variable running and keep the while loop true allows me to turn on/off the method while keeping the thread open. Thank you Jaboyc
private void runInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
if(running){
try {
checkPixel();
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
Would this work
while (true) {
if (running) {
doStuff();
}
}
in the run method?
I am trying to set a button to green for 1 second, then back to red. But It won't change to green anymore, if I comment out the "change to red" part, it will turn green fine. I have used Log.d and it shows that there is a second difference between changing from "change to green" to "change to red" so you should see the green before the red, but for some reason this is not working.
Any Ideas?
public void level1() throws InterruptedException {
int Low = 1000;
int High = 3000;
int t = r.nextInt(High-Low) + Low;
Thread.sleep(t);
handleTime.post(new Runnable() {
#Override
public void run() {
int i = r.nextInt(5);
switch(i) {
case 1:
try {
setGreen(tLeft);
tLActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
tLActive = false;
setRed(tLeft);
}
break;
case 2:
try {
setGreen(tRight);
tRActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
tRActive = false;
setRed(tRight);
}
break;
case 3:
try {
setGreen(center);
cActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
cActive = false;
setRed(center);
}
break;
case 4:
try {
setGreen(bLeft);
bLActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
bLActive = false;
setRed(bLeft);
}
break;
case 5:
try {
setGreen(bRight);
bRActive = true;
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
bRActive = false;
setRed(bRight);
}
break;
}
}
});
}
private void setGreen(ImageButton b) {
b.setBackgroundResource(R.drawable.green);
Log.d("green", "green");
}
private void setRed(ImageButton b) {
b.setBackgroundResource(R.drawable.red);
Log.d("red", "red");
}
You able to use Handler.class
As simple example:
setGreenColor();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
setRedColor();
}
}, 1000);
where postDelayed will be called in UI thread.
The Runnable in this case runs on the UI thread. The same thread responsible for drawing. But drawing is not immediate instead the UI element gets invalidated because it wants to be redraw and when the UI thread has time it will preform the redraw.
{ //the essence of the runnable code
setGreen(bRight); //UI element is invalidated, it wants to be redrawn green
Thread.sleep(1000); //UI thread is tied up here (blocked) so nothing can happen on UI
setRed(bRight); //UI element is invalidated again, it wants to be redrawn red now
// replacing the green before it's even been seen
} //end of runnable code
//now the redrawing occurs, and it will only be red.
As Eldar Mensutov points out one solution is to post another runnable with a delay. That way the UI thread will not be blocked by the Thread.sleep.
Iam making app for listening .mp3 words in greek language and displaying them after 2000ms but when i pause thread and then notify() back thread never runs again... TextView is changing every 2000ms but when i pause it and notify() run() block is not executing anything anymore and app crashes.. What iam doing wrong ?
class MyinnerThread implements Runnable {
String name;
Thread tr;
boolean suspendFlag;
int i = 0;
MyinnerThread(String threadname) {
name = threadname;
tr = new Thread(this, name);
suspendFlag = false;
tr.start();
}
public void run() {
try {
while(!suspendFlag){
runOnUiThread(new Runnable() {
#Override
public void run() {
if(i == 0){tv1.setText("trhead1");}
if(i == 1){tv2.setText("trhead2");}
if(i == 2){tv3.setText("trhead3");}
if(i == 3){tv4.setText("trhead4");}
if(i == 4){tv5.setText("trhead5");}
if(i == 5){tv6.setText("trhead6");}
if(i == 6){tv7.setText("trhead7");}
if(i == 7){tv8.setText("trhead8");}
synchronized(signal) {
while(suspendFlag) {
try {
signal.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
Thread.sleep(2000);
i++;
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
}
void mysuspend() {
suspendFlag = true;
}
void myresume() {
synchronized(signal) {
suspendFlag = false;
signal.notify();
}
}
}
EDIT: Final code here and working !
run() {
try {
while(true){
synchronized(signal) {
while(suspendFlag) {
try {
signal.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
//....
}
}
});
Thread.sleep(2000);
i++;
}
}
}
}
signal.wait() is called from within the UI thread (I assume, runOnUIThread will execute the given Runnable on the UI thread). This will block/freeze the UI. Take it out of the run() method and put into the threads 'main loop'.
Rethink the main loop while (!suspendFlag)! This will abort the entire task instead of just suspending it.
Finally, make suspendFlag volatile to avoid visibility issues.
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) {
}
}
}
I have a class Automator that can automate a user. I am specifically having problems setting the system clipboard in windows. The Automator class makes use of the ClipSetThread class, which is a thread that sets the system clipboard. A instance of ClipSetThread takes as input a thread, that if null, it joins with (waits for it to complete).
I feel that I am not calling ClipSetThread right because I still have the errors I have had before in its reliability; prior to the ClipSetThread. This code does not throw any errors when it runs, it works about 2/3 of the time though. Other times it will print 1134, _234, or etc. It seems that the threads are not joining (waiting for) each other, or get skipped.
Code:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;
public class Automator extends Thread implements NativeMouseInputListener
{
Robot rob = null;
TheAppClass theApp = null;
ClipSetThread lastClipSet = null;
boolean doit = false;
boolean settingClip = false;
public void run()
{
try // to make the Global hook
{
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex){theApp.updateOutput("No Global Keyboard or Mouse Hook");return;}
try // to create a robot (can simulate user input such as mouse and keyboard input)
{
rob = new Robot();
}
catch (AWTException e1) {theApp.updateOutput("The Robot could not be created");return;}
while(true) {}
}
public void setApp(TheAppClass app)
{
theApp = app;
theApp.updateOutput("Succesfully started automator");
}
public void setClip(String arg)
{
ClipSetThread set = new ClipSetThread(theApp, lastClipSet);
lastClipSet = set;
set.setClip(arg);
}
public void DOit()
{
theApp.updateOutput("Starting");
pasteAtCursorLocation("1");
tab(1);
pasteAtCursorLocation("2");
tab(1);
pasteAtCursorLocation("3");
tab(1);
pasteAtCursorLocation("4");
tab(1);
theApp.updateOutput("Complete");
}
public void nativeMouseReleased(NativeMouseEvent e)
{
//System.out.println("Mouse Released: " + e.getButton());
if(doit)
{
DOit();
doit = false;
}
}
public void pasteAtCursorLocation(String text)
{
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
}
public void tab(int numTimes)
{
while(numTimes > 0)
{
rob.keyPress(KeyEvent.VK_TAB);
rob.keyRelease(KeyEvent.VK_TAB);
numTimes--;
theApp.updateOutput("Simulated Tab");
}
}
// Unimplemented
public void nativeMouseClicked(NativeMouseEvent arg0) {}
public void nativeMousePressed(NativeMouseEvent arg0) {}
public void nativeMouseDragged(NativeMouseEvent arg0) {}
public void nativeMouseMoved(NativeMouseEvent arg0) {}
}
ClipSetThread:
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
public class ClipSetThread extends Thread
{
Clipboard sysClip = null;
TheAppClass theApp = null;
public ClipSetThread(TheAppClass app, Thread waitFor)
{
theApp = app;
sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
if(waitFor != null)
{try {waitFor.join();}catch (InterruptedException e) {}}
}
public void setClip(String arg)
{
// Two strings that will hopefully never be on the clipboard
String checkStr1 = "9999999999999";
String checkStr2 = "99999999999999";
// When we read in the clipboard we want to see if we change these strings from the ones they
// will never be, if they do change we read the clipboard successfully
String clipBoardTextBefore = checkStr1;
String clipBoardTextAfter = checkStr2;
// First get a copy of the current system clipboard text
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// If we failed to change the string it means we failed to read the text
if(clipBoardTextBefore.equals(checkStr1))
theApp.updateOutput("Could NOT get sysClip text");
else
{
// If we didn't failed to get the current text try to change it
while(true)
{
try{sysClip.setContents(new StringSelection(arg), null);}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// Now again check to see the clipboard text
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextAfter = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// If we failed to read the clipboard text
if(clipBoardTextAfter.equals(checkStr2))
theApp.updateOutput("Could NOT check if sysClip update was successful");
else
{ // We re-read the clipboard text, see if it changed from the original clipboard text
if(clipBoardTextAfter.equals(checkStr1))
theApp.updateOutput("Could NOT successfully set clipboard text");
else
theApp.updateOutput("Set Clipboard Text:" + arg + "\n");
}
}
}
}
So, firstly, you never call start on the ClipSetThread. You should also check to see if the thread is still alive before joining it.
public class ClipSetThread extends Thread {
Clipboard sysClip = null;
TheAppClass theApp = null;
private String toClipboard;
public ClipSetThread(TheAppClass app, Thread waitFor, String toClipBoard) {
theApp = app;
sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
this.toClipboard = toClipBoard;
// !! Check to see if the thread is also alive before trying to join with it...
if (waitFor != null && waitFor.isAlive()) {
try {
waitFor.join();
} catch (InterruptedException e) {
}
}
}
// You should really put your logic into the `run` method in order to allow
// the code to actually run in a separate thread...otherwise there is no
// point in using a thread....
#Override
public void run() {
// Two strings that will hopefully never be on the clipboard
String checkStr1 = "9999999999999";
String checkStr2 = "99999999999999";
// When we read in the clipboard we want to see if we change these strings from the ones they
// will never be, if they do change we read the clipboard successfully
String clipBoardTextBefore = checkStr1;
String clipBoardTextAfter = checkStr2;
// First get a copy of the current system clipboard text
while (true) {
try {
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// If we failed to change the string it means we failed to read the text
if (clipBoardTextBefore.equals(checkStr1)) {
theApp.updateOutput("Could NOT get sysClip text");
} else {
// If we didn't failed to get the current text try to change it
while (true) {
try {
sysClip.setContents(new StringSelection(toClipboard), null);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// Now again check to see the clipboard text
while (true) {
try {
Transferable contents = sysClip.getContents(null);
clipBoardTextAfter = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// If we failed to read the clipboard text
if (clipBoardTextAfter.equals(checkStr2)) {
theApp.updateOutput("Could NOT check if sysClip update was successful");
} else { // We re-read the clipboard text, see if it changed from the original clipboard text
if (clipBoardTextAfter.equals(checkStr1)) {
theApp.updateOutput("Could NOT successfully set clipboard text");
} else {
theApp.updateOutput("Set Clipboard Text:" + toClipboard + "\n");
}
}
}
}
}
As per our previous converstaion, it's dangerous to use while (true) {}, it's also wasteful, as it will consume CPU cycles unnecessarily...
public class Automator extends Thread implements NativeMouseInputListener {
// A "locking" object...
private static final Object WAIT_LOCK = new Object();
Robot rob = null;
TheAppClass theApp = null;
ClipSetThread lastClipSet = null;
boolean doit = false;
boolean settingClip = false;
public void run() {
try // to make the Global hook
{
GlobalScreen.registerNativeHook();
} catch (NativeHookException ex) {
theApp.updateOutput("No Global Keyboard or Mouse Hook");
return;
}
try // to create a robot (can simulate user input such as mouse and keyboard input)
{
rob = new Robot();
} catch (AWTException e1) {
theApp.updateOutput("The Robot could not be created");
return;
}
// This is wasteful...
// while (true) {
// }
// Locks do not consume CPU cycles while in the wait state...
synchronized (WAIT_LOCK) {
try {
WAIT_LOCK.wait();
} catch (Exception exp) {
}
}
}
public void dispose() {
// Tell the thread it can terminate...
synchronized (WAIT_LOCK) {
WAIT_LOCK.notify();
}
// This will STOP the current thread (which called this method)
// while the lastClipSet finishes...
if (lastClipSet != null && lastClipSet.isAlive()) {
lastClipSet.join();
}
}
public void setClip(String arg) {
ClipSetThread set = new ClipSetThread(theApp, lastClipSet, arg);
lastClipSet = set;
// You MUST START the thread...
set.start();
}
/*...*/
}
Updated
This code could produce a infinite loop. What happens if the clipboard does not contain a String value??
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
You tend to do this a lot. I might suggest that you provide some kind of "escape" mechanism to allow it to fail after a number of retries...
boolean successful = false;
int retries = 0;
while (!successful && retries < 20) {
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
successful = true;
}
catch(Exception e)
{
retries++;
try {Thread.sleep(20);} catch (InterruptedException e1) {}
}
}
Updated with working example
Okay, that was fun. I've put together a (simple) working example. You will want to open a text editor of some kind. When you run the program, you have 5 seconds to make it active ;)
The only basic change I've made is I set added a auto delay between events of 250 milliseconds (see rob.setAutoDelay(250).
Now, you could also place a delay between each key event as well, using Robot#delay, but that's up to you
public class Engine extends Thread {
private Robot rob = null;
private PasteThread lastClipSet = null;
public void setClip(String arg) {
if (lastClipSet != null && lastClipSet.isAlive()) {
try {
lastClipSet.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
PasteThread set = new PasteThread(arg);
lastClipSet = set;
lastClipSet.start();
}
public void pasteAtCursorLocation(String text) {
System.out.println("Paste " + text);
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
}
public Engine() throws AWTException {
rob = new Robot();
rob.setAutoDelay(250);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
}
pasteAtCursorLocation("This is a simple test, thanks for watching!");
}
public static void main(String[] args) {
try {
new Engine();
} catch (AWTException ex) {
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, null, ex);
}
}
public class PasteThread extends Thread {
private String toPaste;
public PasteThread(String value) {
toPaste = value;
}
#Override
public void run() {
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
System.out.println("Current clipboard contents = " + getClipboardContents(sysClip));
sysClip.setContents(new StringSelection(toPaste), null);
System.out.println("New clipboard contents = " + getClipboardContents(sysClip));
}
public String getClipboardContents(Clipboard clipboard) {
String value = null;
boolean successful = false;
int retries = 0;
while (!successful && retries < 20) {
Transferable contents = clipboard.getContents(null);
if (contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
value = (String) contents.getTransferData(DataFlavor.stringFlavor);
successful = true;
} catch (Exception exp) {
retries++;
exp.printStackTrace();
}
} else {
retries++;
}
}
System.out.println(successful + "/" + retries);
return value;
}
}
}
Could you please try to repeat the Paste action with a sleep 1 second in between
public void pasteAtCursorLocation(String text)
{
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
// put in a sleep 1 second here
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
}
It could be that pasting 2x is giving different results. The reason for this strange behavior could the way Windows manages the clipboard. If pasting 2x the clipboard is giving different result then you know that the root cause for this strange behavior is not to find in your code but how Java and Windows work together.